ReentrantReadWriteLock——读写锁原理

读写锁用的是同一个Sycn同步器,因此等待队列,state等也是使用同一个

下面使用一个案例带大家了解以下读写锁的原理:

1.t1线程获取写锁

t1成功上锁,流程与ReentrantLock加锁相比没有特殊之处,不同的是写锁使用state的低16位,而读锁占了state的高16位

以下是写锁的tryAcquired方法源码:

2.t2线程获取读锁

t2执行r.lock,这时进入读锁的sync.acquiredShared(1)流程,首先会进入tryAcquiredShared流程。如果有写锁占据,且当前线程不是获取写锁线程,那么返回-1表示失败

tryAcquiredShared返回值表示

  • -1表示失败
  • 0表示成功,但是后继节点不会继续被唤醒
  • 正数表示成功,而且数值是还有几个后继节点需要被唤醒,读写锁返回1

tryAcquiredShared方法代码如下:

然后会进入sync.doAcquireShared(1)流程,首先也是调用了addWait添加节点,也是添加两个节点,第一个节点为哨兵节点(不同的是节点被设置为Node.SHARED模式而非Node.EXCLUSIVE模式,注意此时t2仍处于活跃状态)

4.然后t2会获取前驱节点,如果前驱节点是头节点就说明t2是老二节点,还会再次调用tryAcquireShared(1)尝试获取锁

5.如果获取成功,在doAcquireShared内for(;;)循环,第一次在调用shouldParkAfterFailedAcquired(p,node)方法时会将前驱节点的waitStatus设置为-1返回false,就会再次循环尝试tryAcquireShared(1)获取锁如果还不成功,这时调用shouldParkAfterFailedAcquired(p,node)方法发现前驱节点的waitStatus设置为-1将返回ture,就会执行后续的parkAndCheckInterrupt()进行park阻塞

doAcquiredShared方法代码如下:

6.这时又有t3线程过来加读锁,t4线程过来加写锁,就会变成下面局势

7.写锁的unlok流程:

这时会走到写锁的sync.release(1)流程,调用sync,tryRelease(1)成功,变成下面的样子

release代码如下:

tryRelease代码如下:

8.接下来会去执行唤醒流程unparkSuccessor,就是让阻塞的老二节点恢复运行,这时t2在doAcquireShared内parkAndCheckInterrupt阻塞处恢复运行,返回再来一次for循环,执行tryAcquiredShared成功则让读锁计数加一

doAcquireShared代码如下:

9.这时t2线程已经恢复运行了,t2会调用setHeadAndPropagate(node,1)方法,它原本所在节点会被设置为头节点。

10.然后再setHeadAndPropagate方法里还会检查下一个节点是否是shared共享节点,如果是则调用doReleaseShared()将head的状态从-1改为0并且唤醒老二(防止在改动的过程中其他线程来进行干扰,避免重复唤醒),这时t3在doAcquireShared里parkAndCheckInterrupt()处恢复运行(这就是读读并发的原理)

setHeadAndPropagate方法代码:

doReleaseShare方法代码:

这时t3已经恢复运行,接下来t3调用setHeadAndPropagate方法将原有节点设置为头节点

11.t2 r.unlock,t3 r.unlock

t2进入sync.releaseShared(1)中,调用tryReleaseShared(1)让计数减一,但是由于计数还不为零,所以不执行doReleaseShared方法

t3进入sync.tryReleaseShared(1)中,调用tryReleaseShared(1)让计数减一,这时计数为零了,进入doReleaseShared方法将头节点的waitStatus从-1改为0,然后唤醒第二节点

之后t4在acquireQueued中parkAndCheckInterrupt处恢复运行,再次for(;;)这次自己是老二线程,并且没有其他竞争,tryAcquired(1)成功,修改头节点,流程结束

  • 15
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值