synchronized和ReentrantLock

本文深入探讨了线程安全的重要性,包括原子性、可见性和有序性。对比了Java中的ReentrantLock和synchronized,两者都是可重入锁,确保线程安全和互斥。ReentrantLock提供了更细粒度的控制,如公平性选择、超时获取锁、中断响应及锁状态检查,而synchronized则是隐式获取和释放,且不具备公平性。此外,synchronized默认使用偏斜锁和轻量级锁优化,但在高竞争情况下会升级为重量级锁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        线程安全是一个多线程环境下正确性的概念,也就是保证多线程环境下共享的、可修改的状态的正确性,这里的状态反映在程序中其实可以看作是数据。

        线程安全需要保证几个基本特性:

  • 原子性,简单说就是相关操作不会中途被其他线程干扰,一般通过同步机制实现。
  • 可见性,是一个线程修改了某个共享变量,其状态能够立即被其他线程知晓,通常被解释为将线程本地状态反映到主内存上,volatile 就是负责保证可见性的。
  • 有序性,是保证线程内串行语义,避免指令重排等。.

ReentrantLock

        可重入锁表示当一个线程试图获取一个它已经获取的锁时,这个获取动作就自动成功,这是对锁获取粒度的一个概念,也就是锁的持有是以线程为单位而不是基于调用次数。Java 锁实现强调再入性是为了和 pthread 的行为进行区分。

        再入锁可以设置公平性(fairness),我们可在创建再入锁时选择是否是公平的。

 ReentrantLock fairLock = new ReentrantLock(true);

        这里所谓的公平性是指在竞争场景中,当公平性为真时,会倾向于将锁赋予等待时间最久的线程。公平性是减少线程“饥饿”(个别线程长期等待锁,但始终无法获取)情况发生的一个办法。

        如果使用 synchronized,我们根本无法进行公平性的选择,其永远是不公平的,这也是主流操作系统线程调度的选择。

        ReentrantLock 相比 synchronized,因为可以像普通对象一样使用,所以可以利用其提供的各种便利方法,进行精细的同步操作,甚至是实现 synchronized 难以表达的用例,如:

  • 带超时的获取锁尝试。
  • 可以判断是否有线程,或者某个特定线程,在排队等待获取锁。
  • 可以响应中断请求。

synchronized

        synchronized 代码块是由一对儿 monitorenter/monitorexit 指令实现的,Monitor 对象是同步的基本实现单元。三种不同的 Monitor 实现,也就是常说的三种不同的锁:偏斜锁(Biased Locking)、轻量级锁和重量级锁。

        当没有竞争出现时,默认会使用偏斜锁。JVM 会利用 CAS 操作(compare and swap),在对象头上的 Mark Word 部分设置线程 ID,以表示这个对象偏向于当前线程,所以并不涉及真正的互斥锁。这样做的假设是基于在很多应用场景中,大部分对象生命周期中最多会被一个线程锁定,使用偏斜锁可以降低无竞争开销。

        如果有另外的线程试图锁定某个已经被偏斜过的对象,JVM 就需要撤销(revoke)偏斜锁,并切换到轻量级锁实现。轻量级锁依赖 CAS 操作 Mark Word 来试图获取锁,如果重试成功,就使用普通的轻量级锁;否则,进一步升级为重量级锁。

        当 JVM 进入安全点(SafePoint)的时候,会检查是否有闲置的 Monitor,然后试图进行降级。

两者的共同点

1. 都是用来协调多线程对共享对象、变量的访问

2. 都是可重入锁,同一线程可以多次获得同一个锁

3. 都保证了可见性和互斥性

两者的不同点

  • ReentrantLock显示的获得、释放锁,synchronized隐式获得释放锁
  • sychronized是一个关键字,是JVM层面的锁,ReentrantLock是一个类,是API层面的锁。
  • 底层实现不一样, synchronized是同步阻塞,使用的是悲观并发策略,lock是同步非阻塞,采用的是乐观并发策略
  • synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁。
  • Sychronized是非公平锁,ReentrantLock可以选择公平锁和非公平锁。
  • ReentrantLock可响应中断、可轮回,synchronized是不可以响应中断的,为处理锁的不可用性提供了更高的灵活性
  • Synchronized有一个锁升级的过程。
  • ReentrantLock可支持选择性唤醒通知
  • 通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值