ReentrantReadWriteLock源码解析

先看到构造方法

	public ReentrantReadWriteLock() {	
		//无惨构造函数,默认非公平锁
        this(false);
    }
    public ReentrantReadWriteLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
        readerLock = new ReadLock(this);
        writerLock = new WriteLock(this);
    }
    //FairSync和NonfairSync继承Sync
    Sync() {
    	//该属性读锁会用到 ,用来记录各个线程的加读锁的次数
        readHolds = new ThreadLocalHoldCounter();
        setState(getState()); // ensures visibility of readHolds
    }
    //重写initialValue,返回一个HoldCounter
    static final class ThreadLocalHoldCounter
        extends ThreadLocal<HoldCounter> {
        public HoldCounter initialValue() {
            return new HoldCounter();
        }
    }
    static final class HoldCounter {
    	//读锁加锁的次数
        int count = 0;
        //线程id
        final long tid = getThreadId(Thread.currentThread());
    }

写锁

先看到写锁的加锁过程

		public void lock() {
			//调用到aqs的acquire方法,acquire方法之前文章已经解析过了
            sync.acquire(1);
        } 
        //看到ReentrantReadWriteLock对tryAcquire的实现
        protected final boolean tryAcquire(int acquires) {
           	//获取当前线程
            Thread current = Thread.currentThread();
            //获取aqs的state
            int c = getState();
            //计算state的后16位的值,用来表示写锁的state值
            //c & 65535 (后16为全部为1,前16位全部为0) 
            int w = exclusiveCount(c);
            //已经有线程上了锁了,可能是写锁,也可能是读锁
            if (c != 0) { 
                if (w == 0 || current != getExclusiveOwnerThread())
                	//w==0 上的不是写锁 ,被上了读锁,则不让上写锁。
                	//或者 w=!0 被上了写锁,current != getExclusiveOwnerThread() ,且上写锁的不是自己。
                	//加锁失败,去排队。
                    return false;
                //w != 0 且 current == getExclusiveOwnerThread() 自己重入上写锁,只有16位表示,不能超过65535
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                //重入,增加state值
                setState(c + acquires);
                //加锁成功
                return true;
            }
            //没有被上锁
            //writerShouldBlock判断是否需要去排队
            //如果不需要排队  , cas设置state的值 
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                //writerShouldBlock返回true , 需要排队 , 则返回false 加锁失败
                //cas失败,则说明被其他线程抢到了锁, 则返回false 加锁失败
                //排队去。
                return false;
            //cas设置state的值 成功,将当前持有锁的设置为自己
            setExclusiveOwnerThread(current);
            //返回true 加锁成功
            return true;
        }

writerShouldBlock方法

		//FairSync公平锁的实现
		final boolean writerShouldBlock() {
			//该方法之前的文章已经解析过了,判断队列里是否有其他线程在排队
            return hasQueuedPredecessors();
        }
        //NonfairSync非公平锁的实现
        final boolean writerShouldBlock() {
        	//直接返回false
            return false;
        }

再看到写锁的解锁过程

		public void unlock() {
			//调用到aqs的release方法,release方法之前文章已经解析过了
            sync.release(1);
        }
        //看到ReentrantReadWriteLock对tryRelease的实现
        protected final boolean tryRelease(int releases) {
       		//持有锁的线程不是当前线程报错
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            //state减去releases的值
            int nextc = getState() - releases;
            //判断state后16位的值,是否为0
            boolean free = exclusiveCount(nextc) == 0;
            //为0,将当前线程设置为空
            if (free)
                setExclusiveOwnerThread(null); 
            //将减去后的值,设置回state
            setState(nextc); 
            //为0返回true,解锁成功
            return free;
        }

读锁

先看到读锁的加锁过程

		public void lock() {
            sync.acquireShared(1);
        }
        public final void acquireShared(int arg) {
        	//加读锁
        	if (tryAcquireShared(arg) < 0)
        		//加读锁失败,要去排队
            	doAcquireShared(arg);
    	}
    	private void doAcquireShared(int arg) {
    		//addWaiter之前文章以及分析过了
    		//将当前线程包装为node,然后进入同步等待队列排队,这里传入了一个Node.SHARED参数,赋值node的nextWaiter属性,以此来标识这个node是一个读锁的节点
	        final Node node = addWaiter(Node.SHARED);
	        boolean failed = true;
	        try {
	            boolean interrupted = false;
	            //死循环
	            for (;;) {
	            	//获取node的前一个节点
	                final Node p = node.predecessor();
	                //p如果为头结点
	                if (p == head) {
	                	//加读锁,读锁的tryAcquireShared只会返回1和-1,1标识加锁成功,-1标识加锁失败
	                    int r = tryAcquireShared(arg);
	                    //加锁成功
	                    if (r >= 0) {
	                    	//设置自己为头结点,并唤醒后面的连续的读锁节点
	                        setHeadAndPropagate(node, r);
	                        //将p的next属性清空
                            p.next = null; // help GC
	                        if (interrupted)
	                        	//如果被打断过,这里打断自己,设置打断标识,表示自己曾经被打断过
	                            selfInterrupt();
	                        failed = false;
	                        return;
	                    }
	                }
	                //shouldParkAfterFailedAcquire之前文章已经分析过了
	                //shouldParkAfterFailedAcquire设置前置节点的waitStatus
	                //parkAndCheckInterrupt进行休眠,醒来后清除打断标识,并返回是否被打断过
	                if (shouldParkAfterFailedAcquire(p, node) &&
	                    parkAndCheckInterrupt())
	                    //被打断过,修改interrupted 为true
	                    interrupted = true;
	            }
	        } finally {
	            if (failed)
	            	//cancelAcquire之前的文章已经分析过了
	            	//在同步等待队列中断开被取消的节点
	                cancelAcquire(node);
        }
    }
    private void setHeadAndPropagate(Node node, int propagate) {
        Node h = head; 
        //设置node为头结点,将node的thread和prev属性置空
        setHead(node); 
        //读锁传进来的propagate 一定大于0 ,后面写Semaphore的时候再来看=0的情况
        if (propagate > 0 || h == null || h.waitStatus < 0 ||
            (h = head) == null || h.waitStatus < 0) {
            //获取node的下一个节点
            Node s = node.next;
            //如果下一个节点也是读锁节点
            if (s == null || s.isShared())
            	//唤醒队列中等待的节点,显然队列中所有连续排队的读锁节点都会被唤醒,直到遇到一个写锁节点,则上处 s.isShared()判断不成立。
                doReleaseShared();
        }
    }
    //读锁的排队等待的node的nextWaiter 属性为SHARED
    //Node类初始化的常量  static final Node SHARED = new Node();
    final boolean isShared() {
        return nextWaiter == SHARED;
    }

tryAcquireShared方法

		protected final int tryAcquireShared(int unused) {
            Thread current = Thread.currentThread();
            //获取state的值
            int c = getState();
            //计算state后16位的值是否为0 , 判断持有锁的线程是否为自己
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                //state后16位的值不为0(已经上了写锁),且持有锁的线程不是自己 
                //返回-1,加锁失败
                return -1;
            //走到这里
            //没有被上写锁
            //或者上写锁的是自己
            //计算state的前16的值 (c >>> 16 右移16位,抛弃后16位)
            int r = sharedCount(c);
            //readerShouldBlock判断是否需要去排队
            if (!readerShouldBlock() &&
                r < MAX_COUNT &&
                compareAndSetState(c, c + SHARED_UNIT)) {
                //读锁不用排队,次数没有超过65535,且cas设置state成功
                //如果r为0,说明没线程在上读锁
                if (r == 0) {
                	//将firstReader 设置为当前线程
                    firstReader = current;
                    //firstReaderHoldCount 为 1
                    firstReaderHoldCount = 1;
                //如果r不为0,但是firstReader是当前线程,重入了
                } else if (firstReader == current) {
                	//firstReaderHoldCount++
                    firstReaderHoldCount++;
                } else {
                	//获取cachedHoldCounter(记录最近一次来拿读锁的线程),多种情况
                	//1. firstReader为线程1,则线程2上读锁时走到这里,此时cachedHoldCounter为空 ,rh 为空
                	//2. firstReader为线程1,当线程2再次上读锁时,cachedHoldCounter不为空 ,rh 不为空, rh.tid != getThreadId(current)不成立 ,rh.count == 0也不成立,只运行rh.count++;
                	//2.1  firstReader为线程1, 线程2释放了全部的读锁(解锁时会扣减count,count为0时,会从readHolds移除),然后线程2再次来加读锁,此时cachedHoldCounter不为空 ,rh 不为空,则走下一个判断rh.count == 0成立;
                	//3.线程3走到这里时,cachedHoldCounter记录的线程2,cachedHoldCounter不为空 ,rh 不为空,rh.tid != getThreadId(current)成立 
                    HoldCounter rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                    	//1. readHolds.get() 此时HoldCounter 的count为0,cachedHoldCounter 记录的是线程2
                    	//3. readHolds返回一个新的HoldCounter ,cachedHoldCounter此时 记录的是线程3
                        cachedHoldCounter = rh = readHolds.get();
                    //2.1 走这里
                    else if (rh.count == 0)
                    	//将rh设置回readHolds中
                        readHolds.set(rh);
                    //读次数加一
                    rh.count++;
                }
                //返回1,读锁上锁成功
                return 1;
            }
            //读锁上锁失败,还没完,接着调用fullTryAcquireShared
            return fullTryAcquireShared(current);
        }

readerShouldBlock方法

		//FairSync公平锁的实现
		final boolean readerShouldBlock() {
			//判断队列是否有线程在排队
            return hasQueuedPredecessors();
        }
        
        //NonfairSync非公平锁的实现
        final boolean readerShouldBlock() {
        	//当队列中头节点的下一个节点为写锁的等待节点时,返回true,需要将此时请求上读锁的线程阻塞
        	//防止读操作过多,导致排队的写操作长时间无法进行,导致新来读操作全部脏读
            return apparentlyFirstQueuedIsExclusive();
        }
        final boolean apparentlyFirstQueuedIsExclusive() {
	        Node h, s;
	        //有头结点 头结点赋值给h
	        //头结点有下个节点(正在排队等待的线程) 下个节点赋值给s
	        //s的是否为  共享节点(读锁的节点)
	        //节点的thread属性不为空(还没有被唤醒,并抢锁成功成为头结点)
	        return (h = head) != null &&
	            (s = h.next)  != null &&
	            !s.isShared()         &&
	            s.thread != null;
    	}

fullTryAcquireShared方法

		final int fullTryAcquireShared(Thread current) {
            HoldCounter rh = null;
            //死循环
            for (;;) {
                int c = getState();
                //判断是否被上了写锁
                if (exclusiveCount(c) != 0) {
                	//被上了写锁
                	//判断上写锁的线程是不是自己
                    if (getExclusiveOwnerThread() != current)
                    	//被其他线程上了写锁,返回-1,加锁失败
                        return -1;
                } 
               	//没有被上写锁,判断读锁是否要被阻塞
                else if (readerShouldBlock()) {
                	//读锁需要阻塞 此时不一定需要阻塞,可能是读锁重入
                	//第一个上读锁的是自己
                    if (firstReader == current) {
                       
                    } 
                    //第一个上读锁的不是自己
                    else {
                        if (rh == null) {
                        	//获取cachedHoldCounter
                            rh = cachedHoldCounter;
                            //rh == null ,自己是第二个来上读锁的
                            //rh != null 且 rh.tid != getThreadId(current) 最近一次上读锁的不是自己
                            if (rh == null || rh.tid != getThreadId(current)) {
                            	//获取自己的HoldCounter
                                rh = readHolds.get();
                                //如果是0 ,说明自己当前没有上读锁
                                if (rh.count == 0)
                                	//移除自己的HoldCounter
                                    readHolds.remove();
                            }
                        }
                        //自己当前没有上过读锁的话
                        if (rh.count == 0)
                        	//返回-1,加锁失败
                            return -1;
                    }
                }
                if (sharedCount(c) == MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
				//走到这里,说明当前当前没有写锁,读锁也不用排队
				//cas 修改state
                if (compareAndSetState(c, c + SHARED_UNIT)) {	
                	//cas修改成功
                	//下面代码和tryAcquireShared中加读锁代码一样的了,就不赘述了
                    if (sharedCount(c) == 0) {
                        firstReader = current;
                        firstReaderHoldCount = 1;
                    } else if (firstReader == current) {
                        firstReaderHoldCount++;
                    } else {
                        if (rh == null)
                            rh = cachedHoldCounter;
                        if (rh == null || rh.tid != getThreadId(current))
                            rh = readHolds.get();
                        else if (rh.count == 0)
                            readHolds.set(rh);
                        rh.count++;
                        //读锁加锁成功,修改cachedHoldCounter为自己
                        cachedHoldCounter = rh; // cache for release
                    }
                    //返回1 标识加锁成功
                    return 1;
                }
                //cas修改失败,state被其他线程修改了,接着下一次循环。
            }
        }

看到读锁的解锁流程

		public void unlock() {
            sync.releaseShared(1);
        }
        public final boolean releaseShared(int arg) {
	        if (tryReleaseShared(arg)) {
	        	//如果当前没有线程在加锁,唤醒队列中等待的节点
	            doReleaseShared();
	            return true;
	        }
	        return false;
    	}

releaseShared方法

        protected final boolean tryReleaseShared(int unused) {
            Thread current = Thread.currentThread();
            //firstReader 是否为自己
            if (firstReader == current) {
                // assert firstReaderHoldCount > 0;
                //如果firstReaderHoldCount 为1 ,则该线程的读锁解锁完毕,将firstReader置空
                if (firstReaderHoldCount == 1)
                    firstReader = null;
                //重入次数减一
                else
                    firstReaderHoldCount--;
            } 
            //第一个加读锁的不是自己
            else {
            	//获取最近一次加读锁的HoldCounter
                HoldCounter rh = cachedHoldCounter;
                //如果rh为空
                //或者rh不为空,但是rh.tid != getThreadId(current) 最近一次加读锁的线程不是自己
                if (rh == null || rh.tid != getThreadId(current))
                	//获取到自己的HoldCounter
                    rh = readHolds.get();
                //获取读锁加锁的次数
                int count = rh.count;
                if (count <= 1) {
                	//从readHolds移除自己的HoldCounter
                    readHolds.remove();
                    if (count <= 0)
                        throw unmatchedUnlockException();
                }
                //将读锁加锁次数减一
                --rh.count;
            }
            //死循环
            for (;;) {
                int c = getState();
                //减去65535 , 读锁用的是stated的前16位
                int nextc = c - SHARED_UNIT; 
                //cas设置stated的值 设置不成功说明还有其他线程在加解锁,则接着循环,直至设置成功
                if (compareAndSetState(c, nextc))
                	//返回解锁后的state是否为0,也就是当前是否还有锁(读锁或者写锁)
                    return nextc == 0;
            }
        }

doReleaseShared方法

	private void doReleaseShared() {
		//死循环
        for (;;) {
        	//获取头节点
            Node h = head;
            //如果头结点不为空 且 头结点不等于尾节点
            if (h != null && h != tail) {
                int ws = h.waitStatus;
                //如果节点waitStatus为SIGNAL,则需要唤醒后继节点
                if (ws == Node.SIGNAL) {
                	//cas将节点的waitStatus改为0
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                    	//cas失败,则执行一下次循环
                        continue;            // loop to recheck cases
                    //unparkSuccessor之前的文章以及分析过了
                    //cas成功,唤醒h的后继节点 ,  
                    unparkSuccessor(h);
                }
                //如果头结点的waitstatus为0
                //则 cas 将头结点修改为PROPAGATE,如果cas成功,其实没有什么作用,然后执行后续代码,很可能就跳出循环了。 
                else if (ws == 0 &&
                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    //cas失败反而是有用的,cas失败很可能是队列中进入了节点把头结点的waitstatus修改成了-1
                    //此时执行一下次循环重新获取头结点的waitStatus,可以唤醒刚进来的节点
                    continue;                // loop on failed CAS
            }
            //跳出循环,如果头结点没有发生变化
            //发生变化,再次循环一次
            if (h == head)                   // loop if head changed
                break;
        }
    }

到此,ReentrantReadWriteLock源码也就解析完毕,这里许多aqs的代码,在之前ReentrantLock源码解析文章里面讲过,这里就没赘述了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值