ReentrantLock使用场景和实例

目录

ReentrantLock的源码分析

ReentrantLock.lock() 这个是 reentrantLock 获取锁的入口

acquire 是 AQS 中的方法,如果 CAS 操作未能成功,说明 state 已经不为 0,此 时继续 acquire(1)操作

当 tryAcquire 方法获取锁失败以后,则会先调用 addWaiter 将当前线程封装成 Node. 

 锁的释放流程

原本挂起的线程继续执行 

场景1:如果发现该操作已经在执行中则不再执行(有状态执行)

场景2:如果发现该操作已经在执行,等待一个一个执行(同步执行,类似synchronized)

场景3:如果发现该操作已经在执行,则尝试等待一段时间,等待超时则不执行(尝试等待执行)

场景4:如果发现该操作已经在执行,等待执行。这时可中断正在进行的操作立刻释放锁继续下一操作

下面是ReentrantLock的一个代码示例


ReentrantLock的源码分析

ReentrantLock.lock() 这个是 reentrantLock 获取锁的入口

以非公平锁为例,来看看 lock 中的实现

1. 非公平锁和公平锁最大的区别在于,在非公平锁中我抢占锁的逻辑是,不管有 没有线程排队,我先上来 cas 去抢占一下

2. CAS 成功,就表示成功获得了锁

3. CAS 失败,调用 acquire(1)走锁竞争逻辑 

CAS 的实现原理

通过 cas 乐观锁的方式来做比较并替换,这段代码的意思是,如果当前内存中的 state 的值和预期值 expect 相等,则替换为 update。更新成功返回 true,否则返 回 false. 这个操作是原子的,不会出现线程安全问题,这里面涉及到Unsafe这个类的操作, 以及涉及到 state 这个属性的意义。 state 是 AQS 中的一个属性,它在不同的实现中所表达的含义不一样,对于重入 锁的实现来说,表示一个同步状态。它有两个含义的表示

1. 当 state=0 时,表示无锁状态

2. 当 state>0 时,表示已经有线程获得了锁,也就是 state=1,但是因为 ReentrantLock 允许重入,所以同一个线程多次获得同步锁的时候,state 会递增, 比如重入 5 次,那么 state=5。而在释放锁的时候,同样需要释放 5 次直到 state=0 其他线程才有资格获得锁

acquire 是 AQS 中的方法,如果 CAS 操作未能成功,说明 state 已经不为 0,此 时继续 acquire(1)操作

 这个方法的主要逻辑是

1. 通过 tryAcquire 尝试获取独占锁,如果成功返回 true,失败返回 false

2. 如果 tryAcquire 失败,则会通过 addWaiter 方法将当前线程封装成 Node 添加 到 AQS 队列尾部

3. acquireQueued,将 Node 作为参数,通过自旋去尝试获取锁。

当 tryAcquire 方法获取锁失败以后,则会先调用 addWaiter 将当前线程封装成 Node. 

如果 ThreadA 还在执行中没有释放锁的话,意味着 ThreadB 和 ThreadC 只能挂起了。
 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值