JAVA并发编程(12)-读写锁ReentrantReadWriteLock的实现分析

读写锁
读写锁分为读锁和写锁两个部分。读的部分是共享的,可以多个线程同时使用。写锁时互斥的。同一时刻只有一个线程可以写。并且写的时候不允许读。
我们知道AQS维护了一个 int类型的同步状态变量state。那如何用一个变量来实现读写的复杂控制呢?使用按位分段保存。一个int类型变量有32位二进制组成。将这32位分为高16位和低16位,高16位保存读状态,低16位保存写状态。如下图
在这里插入图片描述
那如何快速获取读写状态呢?通过位运算。假设当前同步状态值为S,写状态等于S&0x0000FFFF(将高16位全部抹去),读状态等于S>>>16(无符号补0右移16位)。当写状态增加1时,等于S+1,当读状态增加1时,等于S+(1<<16),也就是S+0x00010000。

写锁的获取与释放
什么情况下可以获取写锁呢?
1、读写锁都没有被获取 AQS同步状态=0
2、当前线程获取了写锁(当前线程获取了读锁是不能获取写锁的,因为 这个锁不支持锁升级)
所以获取写锁代码如下:代码1 的条件过滤后就是情况2,代码2就是情况1 这两种情况尝试获取写锁。
在这里插入图片描述
写锁的释放同重入锁。因为互斥所以释放锁是单线程的。逻辑比较简单

读锁的获取与释放

读锁是共享的,那么什么时候允许获取读锁呢?
1、读写锁都没有被获取 AQS同步状态=0
2、写锁没有被获取,那么读锁是共享的 ,可以继续获取
3、写锁被当前线程获取了。当前线程还可以继续获取读锁。(获取读锁后释放写锁就是锁降级)

以上三中情况的相反的情况就是 如果一个其他线程获取了写锁则不能获取读锁。其他情况下都能获取。获取读锁代码如下:
截图中标出的代码就是排除这种情况,其他情况下都正常获取读锁。
在这里插入图片描述

读锁的释放就依靠 cas更新读锁状态就行。当读锁状态=0时就是彻底释放。

锁降级
上文中我们知道一个线程在持有写锁的情况下,还可以同时持有读锁。获取读锁后如果释放写锁,就实现了锁降级。
原书中对锁降级必要性描述如下:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

catch that elf

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

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

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

打赏作者

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

抵扣说明:

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

余额充值