线程进阶 --- synchronized 和 ReentrantLock

目录

一、synchronized 锁

1. 偏向锁

2. 轻量级锁(自适应的自旋锁)

3. 重量级锁

二、ReentrantLock

1. ReentrantLock 相关介绍 

2. ReentrantLock 的用法:

三、ReentrantLock 和 synchronized 的区别

四、我们使用的时候如何选择呢?


Gitee地址:想看博客代码??点击这里


一、synchronized 锁

sychronized 加锁是一个自适应的过程,减少了程序员使用时的负担。会根据情况依次进行锁升级,无锁 --> 偏向锁 --> 轻量级锁 --> 重量级锁。

1. 偏向锁

一个例子:

A和B是情侣  A答应B不结婚也会一直在一起------>这就是偏向锁,避免了高成本的结婚操作(加锁)。而有一天  一个帅哥出现在了A的身边 ,这时候就有必要结婚(加锁)。

  • 并不是真正的加锁,只是一个名分。
  • 偏向锁不是真的“加锁”,只是给对象头中做一个“偏向锁的标记”,记录这个锁属于哪个线程。
  • 偏向锁本质上属于“延迟加锁”,也就是说 能不加锁就不会加锁,从而来避免不必要的加锁开销。

2. 轻量级锁(自适应的自旋锁)

倘若偏向锁不够用,虚拟机并不会立即升级为重量级锁,它还会尝试使用一种称为轻量级锁的优化手段(1.6之后加入的),此时Mark Word 的结构也变为轻量级锁的结构。

  • 轻量级锁通过CAS来实现的,通过CAS检查并更新一块内存(比如null => 该线程的使用),如果更新成功,则认为加锁成功。如果更新失败,则认为锁被占用,一直自旋式的等待。
  • 轻量级锁能够提升程序性能的依据是“对绝大部分的锁,在整个同步周期内都不存在竞争”,注意这是经验数据。
  • 轻量级锁所适应的场景是线程交替执行同步块的场合,如果存在同一时间访问同一锁的场合,就会导致轻量级锁膨胀为重量级锁。

3. 重量级锁

如果竞争进一步激烈,自旋锁也不够用,不能快速获取到锁的状态,就会膨胀为重量级锁。这里的重量级锁就是指 内核提供的 mutex

  • 执行加锁操作,先进入内核态
  • 在内核态判定当前锁是否已经被占用
  • 如果锁没有被占用,则说明加锁成功,并切回到用户态
  • 如果被占用了,加锁失败,此时进入锁的等待队列,挂起,等待被操作系统唤醒
  • 经历了一些沧海桑田,这个锁就被释放后,操作系统也想起了这个挂起的线程,于是唤醒这个线程,并且尝试重新获取锁

二、ReentrantLock

1. ReentrantLock 相关介绍 

属于 JUC(java.util.concurrent ) 中常见的类

是一个可重入互斥锁。 功能和 synchronized 一样 都是用来实现互斥效果,保证线程安全。

2. ReentrantLock 的用法:

  • lock () :加锁,如果获取不到锁就 死等
  • trylock ( 超时时间 ) :尝试加锁加锁,能加酒驾,不能加就不加。可以设置等待时间
  • unlock() :解锁
  • 可以实现公平锁:ReentranLock 默认是不公平的,如果在构造的时候传入一个 true 参数就编程公平锁了。(      ReentrantLock locker = new ReentrantLock(true)     )

三、ReentrantLock 和 synchronized 的区别

  • synchronized 是一个关键字,JVM内部实现的。ReentrantLock 是一个标准库中的类,在JVM外使用 java 代码实现。
  • synchronized 使用的时候不需要手动释放锁,ReentrantLock 使用需要手动释放锁。
  • synchronized 申请锁失败会一直等带别的线程释放锁,ReentrantLock 可以通过trylock 方法等待一段时间就放弃申请锁。
  • synchronized 是非公平锁,ReentrantLock 默认是非公平锁,但可以构造的时候传一个 true 开启公平锁模式。
  • synchronized 是通过Object的 wait 、notify 实现 等待、唤醒,每次唤醒的是一个随机的进程。ReentrantLock 搭配 Condition 类 实现 等待、唤醒,可以更加精确的唤醒某个指定的线程。

四、我们使用的时候如何选择呢?

  • 锁竞争不激烈的时候,使用 synchronized,效率更高,自动释放更方便
  • 锁竞争激烈的时候,使用 ReentrantLock,搭配 trylock 更灵活控制加锁的行为,不会死等
  • 如果需要公平锁,使用 ReentrantLock  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shn!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值