Synchronized与ReentrantLock的区别?

 Synchronized和ReentrantLock都是Java中用于实现线程同步的机制,它们各有优缺点和适用场景。以下是它们的比较和适用示例:

 相似之处:
  1.线程安全:两者都可以用于实现对临界区的保护,从而实现线程安全。
  2.可重入性:两者都支持可重入性,允许一个线程多次获取同一把锁而不会发生死锁。
  3.互斥锁:本质上都是互斥锁,确保在同一时刻只有一个线程能执行被同步的代码块。

 区别:
  1.灵活性:
   synchronized是Java语言的内置特性,使用简单,但功能有限。
   ReentrantLock是一个类,提供了更高级的锁功能,例如:可中断的锁获取、超时获取锁、非阻塞尝试获取锁以及可实现更复杂的同步结构。
  2.性能:
   在较低竞争时,synchronized会自动使用优化,比如锁消除和锁粗化,使得它的性能在某些情况下可能高于ReentrantLock。
   ReentrantLock可能在高竞争下表现更好,因为它可以提供非公平和公平锁模式,公平模式会严格按照请求锁的顺序来分配锁。
  3.实现的功能:
   ReentrantLock提供了更多控制功能,如lock()、unlock()方法,可在任何位置灵活调用。而synchronized在语法上是强制块结束时锁自动释放。
   ReentrantLock提供tryLock()和lockInterruptibly()方法,以响应中断和超时。
  4.条件变量:
   ReentrantLock具有与之关联的Condition对象,可以搭配lock来更细粒度的控制线程通信。
   synchronized配合Object的wait()和notify()/notifyAll()来进行线程之间的通信,但不如Condition灵活。

 适用场景:
  synchronized:适用于简单的同步需求。由于其语法简单且嵌入在Java语言中,特别适合锁定范围与方法等价的情况。小规模、多线程竞争不高的情况下表现优异。适合开发者不想处理锁的复杂生命周期时使用。
  ReentrantLock:适用于需要更高级的同步控制,或者锁定范围与方法不同时。特别是在需要公平锁、可中断锁操作、尝试获取带超时功能的锁,或者需要多个条件等待时,应选择ReentrantLock。当系统规模较大、线程数较多,且具有复杂同步需求的情境时表现突出。

 选择一个合适的锁机制,将有助于提升应用程序的性能并简化并发代码的编写。

  • 补充

 synchronized关键字本身并没有直接使用AQS的state变量,它在JVM底层的实现与state所代表的同步状态概念是类似的:
 记录锁的持有状态:JVM 在对象头中维护了一些信息来记录对象锁的状态,类似于 AQS 中的 state 变量。当线程第一次获取 synchronized 锁时,会标记该对象处于锁定状态;当线程重入锁时,会对锁的持有次数进行记录。
 释放锁的判断:就像AQS中通过state减为0来判断锁是否完全释放一样,synchronized锁在JVM 底层也会根据锁的持有次数来判断是否可以释放锁。只有当线程所有的重入操作都完成,锁的持有次数降为0时,才会真正释放锁,允许其他线程获取该锁。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; ...
    朱森阅读 8,812评论 3 44
  • JavaScript语言精粹 前言 约定:=> 表示参考相关文章或书籍; JS是JavaScript的缩写。 本书...
    微笑的AK47阅读 3,666评论 0 3
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 14,743评论 0 38
  • 数组在程序设计中,为了处理方便, 把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称...
    朱森阅读 9,551评论 2 13
  • 学习内容全局变量与局部变量switch语句for循环while循环Break与Continue关键字printf与...
    零散的蒲公英阅读 3,369评论 0 0