从ReentrantLock看AQS(三)

上篇文章主要介绍了ReentrantLock的lock方法,这次来看看unlock的底层是如何实现的。

release

如前面所说,release是AQS的模板方法,tryRelease由子类实现。tryRelease成功后,便会调用unparkSuccessor唤醒后继节点。h.waitStatus != 0对于ReentrantLock来说就是waitStatus为-1,也就是SIGNAL的情况,如果一个节点的waitStatus为-1,它就有责任唤醒后继节点。
此方法执行完后

	//unlock调用AQS的release
	public void unlock() {
	        this.sync.release(1);
	    }

	//AQS的release方法
	public final boolean release(int arg) {
	        if (this.tryRelease(arg)) {
	            AbstractQueuedSynchronizer.Node h = this.head;
	            if (h != null && h.waitStatus != 0) {
	                //唤醒后继节点
	                this.unparkSuccessor(h);
	            }
	
	            return true;
	        } else {
	            return false;
	        }
	    }

unparkSuccessor

此方法的作用是唤醒节点中park的线程。需要注意的是,我们前面说过CHL队列的头节点是dummyHead,作用是标记,里面不放线程信息。所以此方法传入的形参节点是真正被唤醒节点的上一个waitStatus为-1的队列头节点。

	private void unparkSuccessor(AbstractQueuedSynchronizer.Node node) {
	        int ws = node.waitStatus;
	        if (ws < 0) {//将node的waitStatus设为0,即正常状态
	            node.compareAndSetWaitStatus(ws, 0);
	        }
	
			//获取node的下一个节点
	        AbstractQueuedSynchronizer.Node s = node.next;
	        //如果s是CANCEL状态(1),则从队列尾部向前找到可唤醒状态的节点
	        if (s == null || s.waitStatus > 0) {
	            s = null;
	
	            for(AbstractQueuedSynchronizer.Node p = this.tail; p != node && p != null; p = p.prev) {
	                if (p.waitStatus <= 0) {
	                    s = p;
	                }
	            }
	        }
			//unparks节点里的线程
	        if (s != null) {
	            LockSupport.unpark(s.thread);
	        }
	
	    }

在这里插入图片描述

tryRelease

在这里插入图片描述

protected final boolean tryRelease(int releases) {
			//解锁的逻辑就是state-1
            int c = this.getState() - releases;
            //互斥锁,如果当前持锁的不是自己直接抛异常了
            if (Thread.currentThread() != this.getExclusiveOwnerThread()) {
                throw new IllegalMonitorStateException();
            } else {
                boolean free = false;
                if (c == 0) {//state如果解锁之后状态为0,则释放锁,否则不释放锁
                    free = true;
                    this.setExclusiveOwnerThread((Thread)null);
                }
				//锁重入情况,此时依旧持有锁,只不过state--
                this.setState(c);
                //释放失败,自己依旧持有锁
                return free;
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值