深入ReentrantReadWriteLock

简介: 深入ReentrantReadWriteLock

ReentrantReadWriteLock出现的原因

  • 首先synchronized和ReentrantLock都是互斥锁,一个线程在获取锁资源之后另一个线程只能等待
  • 假设有一种情况是读多写少,并且确保线程安全。可以使用ReentrantReadWriteLock实现
  • ReentrantReadWriteLock的特点是读读不互斥,可以并发执行;读写操作则是互斥的。

代码效果显示

/**
 * @author 舒一笑
 * @date 2023/6/1
 */
public class Test17 {

    static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    static ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
    static ReentrantReadWriteLock.ReadLock readLock =lock.readLock();

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            // 这里现在是读锁
            readLock.lock();
            try {
                System.out.println("子线程是读锁");
                Thread.sleep(50000000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                readLock.unlock();
            }
        }).start();

        Thread.sleep(1000);
        // 这里现在也是读锁
        readLock.lock();
        try {
            System.out.println("主线程");
        } finally {
            readLock.unlock();
        }

    }
}
  • 读读锁效果演示

  • 写读锁效果演示

ReentrantReadWriteLock(重新输入读写锁定)锁的实现原理分析

  • 还是基于AQS实现,同样都是对state的操作。获取锁资源成功便执行判断之后的方法体逻辑,否则便会阻塞到AQS队列中去排队


  • 查看对AQS方法在ReentrantReadWriteLock中的实现可以知道
  • 读锁操作是基于state的高16位的操作
  • 写锁操作是基于state的低16位的操作,所以在锁重入的时候同样是对state的操作,但是范围却比小了


  • ReentrantReadWriteLock依旧是可重入锁
    tryAcquire(int acquires)方法的分析
  • 当前线程不持有锁资源,c的值是0;尝试获取锁资源、CAS拿锁。


写锁释放锁流程和源码分析

  • tryRelease(arg)方法分析

读锁分析

  • 读锁加锁源码分析
  • 方法体里面没拿到锁资源就去排队

  • tryAcquireShared(arg)方法分析

  • 读锁重入流程分析
  • 读锁的重入主要就是基于下面这部分的源码的实现。
  • 通过对r是否为0的判断来证明当前是不是第一个拿到读锁资源的线程
  • 判断满足那么将firstRead置为当前线程。并将firstReadCount置为1
  • 要是第一个判断不满足。那么便会判断当前线程是不是第一个获取读锁资源的线程。要是是的话那么就会firstReadHoldcount++
  • 要是还是不满足那么就说明当前线程不是第一个获取读锁资源的线程。那就在方法体中获取最后一个拿到锁资源的线程。并判断当前线程是否是最后一个拿到读锁资源的线程。要是不是那就将当前线程设置为cachedHoldCounter。
  • 如果在最内部的判断中当前线程是之前的cachedHoldCounter,那就判断当前的重入次数是不是0,重新设置当前线程锁重入信息到readHolds,就是包装了ThreadLocal中,完成初始化操作。重入次数是0;将count次数++

  • 读锁加锁后续fullTryAcquireShared(current)方法分析

  • 读锁在获取锁资源之后doAcquireShared(arg)方法分析

    setHeadAndPropagate(node, r);方法分析

读锁释放锁流程

  • doReleaseShared()方法分析
目录
相关文章
ReentrantReadWriteLock读写锁
ReentrantReadWriteLock读写锁
|
7月前
|
安全 Java
ReentrantLock、ReentrantReadWriteLock、StampedLock讲解
ReentrantLock、ReentrantReadWriteLock、StampedLock讲解
|
6天前
|
缓存 测试技术
ReentrantReadWriteLock 读写锁
ReentrantReadWriteLock 读写锁
26 0
|
11月前
|
Java
16.ReentrantLock全解读
大家好,我是王有志。今天和大家一起聊聊ReentrantLock,它是我们最常见的基于AQS实现的互斥锁。
76 0
|
缓存 Java Linux
ReentrantLock、ReentrantReadWriteLock、StampedLock
ReentrantLock、ReentrantReadWriteLock、StampedLock
ReentrantLock、ReentrantReadWriteLock、StampedLock
ReentrantLock介绍
ReentrantLock介绍
128 0
|
存储 设计模式 Java
深入理解ReentrantLock
同步锁synchronized和重入锁ReentrantLock都是用于并发程序设计必不可少的手段,在JDK 5.0早期版本中,同步锁性能远远低于重入锁,但是在6.0版本之后,jdk对同步锁做了大量的优化,使得同步锁跟重入锁性能差距并不大,并且jdk团队表示,同步锁还有进一步升级优化的空间
深入理解ReentrantLock
|
缓存 Java Android开发
ReentrantReadWriteLock读写锁及其在 RxCache 中的使用
ReentrantReadWriteLock读写锁及其在 RxCache 中的使用
133 0
|
缓存 测试技术
ReentrantReadWriteLock读写锁
ReentrantReadWriteLock是Lock的另一种实现方式,我们已经知道了ReentrantLock是一个排他锁,同一时间只允许一个线程访问,而ReentrantReadWriteLock允许多个读线程同时访问,但不允许写线程和读线程、写线程和写线程同时访问。相对于排他锁,提高了并发性。在实际应用中,大部分情况下对共享数据(如缓存)的访问都是读操作远多于写操作,这时ReentrantReadWriteLock能够提供比排他锁更好的并发性和吞吐量。
100 0
|
Java 容器 安全
ReentrantLock详解
本博客主要讲述ReentrantLock的实现原理,主要内容包括: AQS原理以及实现过程。 ReenetrantLock获取锁、释放锁流程,以及原理。 ReenetrantLock源码分析。
6076 1