ReentrantReadWriteLock源码分析

简介: ReentrantReadWriteLock源码分析

公众号merlinsea


特性:写写互斥,读写互斥,读读共享

锁降级:写线程在获取写锁以后,完成写操作以后可以获取读锁同时释放写锁,即实现了锁降级。


读写锁支持锁降级 为什么不支持锁升级?

答:锁降级是持有写锁的线程,可以进一步持有读锁,因为写锁只能有一个线程持有,因此锁降级不会造成数据的不一致性。锁升级是持有读锁的线程可以进一步持有写锁,因为在读写锁中,读锁可以被多个线程同时持有,如果允许锁升级,那么这些持有读锁的线程都可以申请写锁,这会导致多个线程同时修改共享变量,会造成数据不一致性,因此不支持锁升级。

640.jpg640.jpg

根据上图的代码来解释ReentrantReadWriteLock如何用一个int state变量同时表示读锁和写锁的状态:


java中一个int型的整数是32位,其中用低16位表示写锁的状态,高16位表示读锁的状态
读锁每次重入都加上65536
      0000000000000000  000000000000000
 +    0000000000000001  000000000000000
 --------------------------------------
      0000000000000001  000000000000000
判断有当前有多少线程持有读锁,status>>16
      0000000000000001  000000000000000
>>16
----------------------------------------
     0000000000000000  000000000000001  
写锁每次重入加上1
     0000000000000000  000000000000000
 +   0000000000000000  000000000000001
 --------------------------------------
     0000000000000000  000000000000001
判断有当前线程重入了多少次写锁,status & 65535
    0000000000000001  0000000000000001
  & 0000000000000000  1111111111111111
----------------------------------------
    0000000000000000  0000000000000001


读锁加锁的核心代码

640.jpg


读锁解锁的核心代码注意点:

   1、可以有很多不同的线程持有读锁,故这些持有读锁的线程可以串成一个链表连接。

    2、每个持有读锁的线程内部会记录当前线程重入了多少次读锁 。

   3、每次一个线程释放读锁的时候都要读锁的count--,当某个线程持有读锁次数为0时可以从链表中移除该线程。

640.jpg


写锁加锁核心代码

640.jpg


写锁解锁的核心代码

640.jpg


相关文章
|
6月前
|
设计模式 Java API
StampedLock源码分析(2)
StampedLock也提供了单独读锁和写锁的封装类WriteLockView和ReadLockView,它俩存在的意义就是只讲锁的部分暴露出去,防止外部接口错误加解锁,我觉得符合软件设计模式中的单一职责和接口隔离原则。
34 1
|
7月前
|
Java
【ReentrantReadWriteLock的实现原理】
【ReentrantReadWriteLock的实现原理】
|
6月前
|
Java API
StampedLock源码分析(1)
之前已经说过了ReentrantLock ReentrantReadWriteLock,可以参考之前的博客。在ReentrantReadWriteLock源码解析文末,我提到了ReentrantReadWriteLock的缺点,就是无法避免写线程饥渴的问题,而今天要说的StampedLock提供了乐观读的API,解决了写饥渴的问题。
24 0
|
算法
ReentrantReadWriteLock源码分析
ReentrantReadWriteLock源码分析
33 0
ReentrantReadWriteLock源码分析
AQS(abstractQueuedSynchronizer)锁实现原理详解
AQS(abstractQueuedSynchronizer)抽象队列同步器。其本身是一个抽象类,提供lock锁的实现。聚合大量的锁机制实现的共用方法。
118 0
|
设计模式 Java API
StampedLock源码分析
StampedLock源码分析
69 0
StampedLock源码分析
|
存储 Java
Java并发之AQS源码分析(一)
AQS 全称是 AbstractQueuedSynchronizer,顾名思义,是一个用来构建锁和同步器的框架,它底层用了 CAS 技术来保证操作的原子性,同时利用 FIFO 队列实现线程间的锁竞争,将基础的同步相关抽象细节放在 AQS,这也是 ReentrantLock、CountDownLatch 等同步工具实现同步的底层实现机制。它能够成为实现大部分同步需求的基础,也是 J.U.C 并发包同步的核心基础组件。
105 0
Java并发之AQS源码分析(一)
|
安全 Java
Java并发之AQS源码分析(二)
我在 Java并发之AQS源码分析(一)这篇文章中,从源码的角度深度剖析了 AQS 独占锁模式下的获取锁与释放锁的逻辑,如果你把这部分搞明白了,再看共享锁的实现原理,思路就会清晰很多。下面我们继续从源码中窥探共享锁的实现原理。
126 0
Java并发之AQS源码分析(二)
ReentrantLock 实现原理(上)
使用 synchronize 来做同步处理时,锁的获取和释放都是隐式的,实现的原理是通过编译后加上不同的机器指令来实现。 而 ReentrantLock 就是一个普通的类,它是基于 AQS(AbstractQueuedSynchronizer)来实现的。 是一个重入锁:一个线程获得了锁之后仍然可以反复的加锁,不会出现自己阻塞自己的情况。 AQS 是 Java 并发包里实现锁、同步的一个重要的基础框架。
ReentrantLock 实现原理(下)
使用 synchronize 来做同步处理时,锁的获取和释放都是隐式的,实现的原理是通过编译后加上不同的机器指令来实现。 而 ReentrantLock 就是一个普通的类,它是基于 AQS(AbstractQueuedSynchronizer)来实现的。 是一个重入锁:一个线程获得了锁之后仍然可以反复的加锁,不会出现自己阻塞自己的情况。 AQS 是 Java 并发包里实现锁、同步的一个重要的基础框架。