ReentrantReadWriteLock之深入源码解析

简介

ReentrantLock是排他锁,在高并发读多写少的场景下,同时还要保证线程安全,如果使用ReentrantLock的效率不是那么好,所以才有了ReentrantReadWriteLock。

在讲源码之前,我们对读写锁要有个认知。
读读操作是共享的。
读写操作是互斥的。
写写操作是互斥的。
写读操作是互斥的。(写读两个不同线程)
单线程获取写锁后,再次获取读锁,可以拿到。(写读操作可以重入)
单线程获取读锁后,再次获取写锁,不可以拿到。(A线程拿到读锁,然后在获得写锁修改数据,由于读锁共享,这时B线程拿到读锁读取数据显然数据是有可能是脏数据)

使用方法

public class XxxTest {
   
   
    // 读写锁!
    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 {
   
   
        readLock.lock();
        try {
   
   
            System.out.println("拿到读锁!");
        } finally {
   
   
            readLock.unlock();
        }

        writeLock.lock();
        try {
   
   
            System.out.println("拿到写锁!");
        } finally {
   
   
            writeLock.unlock();
        }
    }
}

源码解析

首先,ReentrantReadWriteLock也是基于AQS实现的,跟ReentrantLock类似,如果不了解,可以看下我的另一篇博客ReetrantLock源码分析,这样学习起来事半功倍。

跟ReetrantLock一样,是否拿到锁资源在于修改AQS的state的值,只不过在ReentrantReadWriteLock中,state的高16位是读锁,低16位是写锁。

从ReentrantReadWriteLock的构造方法看到默认是非公平锁
在这里插入图片描述

写锁加锁源码

在这里插入图片描述

来到AQS的acquire方法,除了tryAcquire方法,其它都跟ReentrantLock一样,我们直接看ReentrantReadWriteLock的tryAcquire方法
在这里插入图片描述

 protected final boolean tryAcquire(int acquires) {
   
   
            /*
             * Walkthrough:
             * 1. If read count nonzero or write count nonzero
             *    and owner is a different thread, fail.
             * 2. If count would saturate, fail. (This can only
             *    happen if count is already nonzero.)
             * 3. Otherwise, this thread is eligible for lock if
             *    it is either a reentrant acquire or
             *    queue policy allows it. If so, update state
             *    and set owner.
             */
             //获取当前线程
            Thread current = Thread.currentThread();
           // 获取state
            int c = getState();
            //获取state低16位写锁
            int w = exclusiveCount(c);
          //  如果c不等于0,说明要么有读锁,要么有写锁
            if (c != 0) {
   
   
                // (Note: if c != 0 and w == 0 then shared count != 0)
                //如果有读锁 或者写锁不是自己 
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                    //进入这里,说明肯定是写锁而且锁的持有者是自己
                   //如果写锁重入次数溢出
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // Reentrant acquire
                获取锁成功
                setState(c + acquires);
                return true;
            }
            //c=0 锁无人持有
            //公平锁看下要不要排队writerShouldBlock->hasQueuedPredecessors()队列有排队返回true,否则反之
            //非公平锁开抢,writerShouldBlock直接返回false
            if (writerShouldBlock() ||
            	//走到这说明不用排队,直接进行CAS开抢
                !compareAndSetState(c,</
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值