深入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()方法分析
目录
相关文章
|
安全 Java
ReentrantLock、ReentrantReadWriteLock、StampedLock讲解
ReentrantLock、ReentrantReadWriteLock、StampedLock讲解
ReentrantReadWriteLock读写锁
ReentrantReadWriteLock读写锁
|
6月前
|
缓存 测试技术
ReentrantReadWriteLock 读写锁
ReentrantReadWriteLock 读写锁
42 0
|
2月前
|
安全 Java
JUC锁: ReentrantReadWriteLock详解
`ReentrantReadWriteLock` 主要用于实现高性能的并发读取,而在写操作相对较少的场景中表现尤为突出。它保证了数据的一致性和线程安全,在合适的场合合理使用 `ReentrantReadWriteLock`,可以实现更加细粒度的控制,并显著提升应用性能。然而,需要注意它的复杂度较一般的互斥锁高,因此在选择使用时要仔细考虑其适用场景。
32 1
|
4月前
ReentrantLock 可重入锁总结
ReentrantLock 可重入锁总结
33 0
|
缓存 Java Linux
ReentrantLock、ReentrantReadWriteLock、StampedLock
ReentrantLock、ReentrantReadWriteLock、StampedLock
ReentrantLock、ReentrantReadWriteLock、StampedLock
|
Java
【Java并发】ReadWriteLock读写锁的使用
【Java并发】ReadWriteLock读写锁的使用
127 0
【Java并发】ReadWriteLock读写锁的使用
|
安全 Java 测试技术
读写锁还不会用StampedLock就Out了
读写锁还不会用StampedLock就Out了
137 0
读写锁还不会用StampedLock就Out了
|
缓存 Oracle 关系型数据库
可重入读写锁ReentrantReadWriteLock的使用详解
ReentrantReadWriteLock是一把可重入读写锁,这篇文章主要是从使用的角度帮你理解,希望对你有帮助。
202 0
可重入读写锁ReentrantReadWriteLock的使用详解
|
Java
彻底理解ReentrantLock可重入锁的使用
java除了使用关键字synchronized外,还可以使用ReentrantLock实现独占锁的功能。而且ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。这篇文章主要是从使用的角度来分析一下ReentrantLock。
200 0
彻底理解ReentrantLock可重入锁的使用