J.U.C.LOCK源码之Condition源码解析

接着上一篇文章接下来就是分析Condition的源码,ConditionObject中是存储了一个单向的连表来保持await队列

	public final void await() throws InterruptedException {
            if (Thread.interrupted()) //如果当前线程被终止则抛出异常
                throw new InterruptedException();
                //把当前的节点增加到ConditionObject中 ,该节点与AQS中的Node一致                
            Node node = addConditionWaiter();
            //把 当前的锁进行释放
            long savedState = fullyRelease(node);
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
            	//判断当前线程是否存在于AQS的队列中如果不存在则进行阻塞,到此await调用完成
                LockSupport.park(this);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }

        private Node addConditionWaiter() {
        	//t 等于最后一个节点
            Node t = lastWaiter;
            //判断当前最后节点是否为空,如果不为空切状态不是CONDITION则把 当前节点增加到最后一个节点
            if (t != null && t.waitStatus != Node.CONDITION) {
                //把当前状态不是CONDITION的Node节点都抛弃
                unlinkCancelledWaiters();
                t = lastWaiter;
            }
            //用当前线程创建一个节点,设置当前状态为CONDITION
            Node node = new Node(Thread.currentThread(), Node.CONDITION);
            //如果为节点是则把当前节点设置为头结点否则在当前节点的末尾增加一个节点
            if (t == null)
                firstWaiter = node;
            else
                t.nextWaiter = node;
            lastWaiter = node;
            return node;
        }
	//释放所有的锁
    final long fullyRelease(Node node) {
        boolean failed = true;
        try {
        //因为锁的重入机制,因此先活的重入的次数然后对锁进行释放
            long savedState = getState();
            if (release(savedState)) {
                failed = false;
                return savedState;
            } else {
                throw new IllegalMonitorStateException();
            }
        } finally {
            if (failed)
                node.waitStatus = Node.CANCELLED;
        }
    }

//判断当前节点是否存在AQS队列中
final boolean isOnSyncQueue(Node node) {
		//当前节点的状态是CONDITION  或者当前节点没有前置节点,那么当前节点就不存在AQS队列中, prev和next是属于AQS的队列中 ,
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
        if (node.next != null) // If has successor, it must be on queue
            return true;
  		//如果都不满足则通过自旋 来判断 当前节点是否存在AQS队列中,如果不存在则进行挂起
        return findNodeFromTail(node);
    }

接下来就是查看当前线程调用single方法实现唤醒线程

	public final void signal() {
		//判断 当前调用的线程 是不是活得锁的线程如果不是 则跑出异常
	    if (!isHeldExclusively())
	        throw new IllegalMonitorStateException();
	    Node first = firstWaiter;
	    //获取 第一个节点然后唤醒 
	    if (first != null)
	        doSignal(first);
	}

   private void doSignal(Node first) {
       do {
           if ( (firstWaiter = first.nextWaiter) == null)
           	//把当前节点从await队列中移除
               lastWaiter = null;
           first.nextWaiter = null;
       } while (!transferForSignal(first) &&
                (first = firstWaiter) != null);
   }

	final boolean transferForSignal(Node node) {
		//把当前节点的waitStatus设置为0,
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;
		//设置以后把当前节点加入到AQS中上篇文章解析㢧改代码
        Node p = enq(node);
        int ws = p.waitStatus;
        //如果当前节点的上一个节点被终止则当前节点会被唤醒
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            LockSupport.unpark(node.thread);
        return true;
    }

到此single的源码解析就完成了,然后接着调用后续的代码

	public final void await() throws InterruptedException {
	    ...
	    while (!isOnSyncQueue(node)) {
	        LockSupport.park(this);
	        //判断当前线程在之后是否被吊用过Interrupt方法
	        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
	            break;
	    }
	    //如果调用过interrupt方法则在吃出判断是跑出异常还是重新 中断
	    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
	        interruptMode = REINTERRUPT;
	    if (node.nextWaiter != null) // 清除 无意义的node
	        unlinkCancelledWaiters();
	    if (interruptMode != 0)
	        reportInterruptAfterWait(interruptMode);
	}

到此Condition源码解析完毕了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值