ReentrantLock中的Condition分析

142 阅读4分钟

Condition类是ReentrantLock的一个内部条件类,用于根据条件唤醒线程和Notify以及NotifyAll一个作用. 下面直接开始看源码:

	//内部维护者一个node双链表队列
	 public class ConditionObject implements Condition, java.io.Serializable {
        private static final long serialVersionUID = 1173984872572414699L;
        /** First node of condition queue. */
        private transient Node firstWaiter;
        /** Last node of condition queue. */
        private transient Node lastWaiter;

        /**
         * Creates a new {@code ConditionObject} instance.
         */
        public ConditionObject() { }

        //新增一个条件等待节点
		//1.判断为节点释放是已经取消的节点,如果是则调用unlinkCancelledWaiters 移除已经被取消的节点
		//2.根据当前线程创建一个Node节点状态为CONDITION的节点
		//3.然后把当前线程的条件节点添加到尾尾部,并且把节点设置为尾节点。
        private Node addConditionWaiter() {
            Node t = lastWaiter;
            // If lastWaiter is cancelled, clean out.
            if (t != null && t.waitStatus != Node.CONDITION) {
                unlinkCancelledWaiters();
                t = lastWaiter;
            }
			//构建节点
            Node node = new Node(Thread.currentThread(), Node.CONDITION);
            if (t == null)
                firstWaiter = node;
            else
                t.nextWaiter = node;
            lastWaiter = node;
            return node;
        }


		//移除被取消的条件节点
		//拿到头节点,然后通过遍历移除已经被取消的节点
        private void unlinkCancelledWaiters() {
            Node t = firstWaiter;
			//记录临时尾节点
            Node trail = null;
            while (t != null) {
				//拿到下一个节点
                Node next = t.nextWaiter;
				//判断当前节点释放被取消
                if (t.waitStatus != Node.CONDITION) {
					//把当前的下一个节点置空
                    t.nextWaiter = null;
					//临时为节点等于null,则存放头节点中
                    if (trail == null)
                        firstWaiter = next;
                    else
						//否则一路记录尾节点
                        trail.nextWaiter = next;
						//最后把尾节点Ithaca成全局节点
                    if (next == null)
                        lastWaiter = trail;
                }
                else
                    trail = t;
                t = next;
            }
        }

     
	 
	    
		//自旋唤醒当个条件节点一直自旋到唤醒为止
        private void doSignal(Node first) {
            do {
                if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                first.nextWaiter = null;
            } while (!transferForSignal(first) &&
                     (first = firstWaiter) != null);
        }

        //遍历每个条件队列的等待节点通过transferForSignal去一个个唤醒。
        private void doSignalAll(Node first) {
            lastWaiter = firstWaiter = null;
            do {
                Node next = first.nextWaiter;
                first.nextWaiter = null;
                transferForSignal(first);
                first = next;
            } while (first != null);
        }

//AQS中的transferForSignal 唤醒条件队列里的节点
    final boolean transferForSignal(Node node) {
        //cas修改状态
        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唤醒
            LockSupport.unpark(node.thread);
        return true;
    }

       //唤醒节点,signal首先唤醒的是头节点,然后调用dosignal进行唤醒操作
        public final void signal() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                doSignal(first);
        }
       //唤醒条件队列里的所有节点。
        public final void signalAll() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                doSignalAll(first);
        }

  

      

        //重新中断标记
        private static final int REINTERRUPT =  1;
        //退出等待是抛出异常状态
        private static final int THROW_IE    = -1;

    
        private int checkInterruptWhileWaiting(Node node) {
            return Thread.interrupted() ?
                (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
                0;
        }
     //根据不同的状态去中断线程
        private void reportInterruptAfterWait(int interruptMode)
            throws InterruptedException {
            if (interruptMode == THROW_IE)
                throw new InterruptedException();
            else if (interruptMode == REINTERRUPT)
                selfInterrupt();
        }

	//不可中断拿到释放锁,进入条件队列
      public final void awaitUninterruptibly() {
		  //构建锁
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            boolean interrupted = false;
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                if (Thread.interrupted())
                    interrupted = true;
            }
            if (acquireQueued(node, savedState) || interrupted)
                selfInterrupt();
        }

		//通过await调整释放锁的线程会生成一个node节点进入这个条件队列
        public final void await() throws InterruptedException {
			//释放被中断你,如果中断则抛出异常
            if (Thread.interrupted())
                throw new InterruptedException();
			//增加一个条件等待节点
            Node node = addConditionWaiter();
			//把锁的持有者线程释放以及状态state修改
            int savedState = fullyRelease(node);
            int interruptMode = 0;
			//判断同步队列里,如果只一个节点则不挂起,
			//或者说该线程本来就在AQS的等待队列里则不用挂起
			//如果不在则需要挂起来
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
			//调用AQS的唤醒其他等待节点的线程,并且如果只有一个自己一个节点则直接获取锁。
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
			//清楚以及被取消的节点
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }
	小结: 通过condition的await方法,会先构建一个条件节点,然后进行锁释放,判断当前条件队列的状态和节点释放已经存在AQS等待队列里如果存在则不用挂起
		最后进行获取锁或者说唤醒AQS等待队列的其他节点,然后进行清理工作清楚已经被取消的节点

//AQS的方法判断队列里释放有该节点或者是
    final boolean isOnSyncQueue(Node node) {
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
        if (node.next != null) // If has successor, it must be on queue
            return true;
     
      
        return findNodeFromTail(node);
    }
//查找Conditino队列的接释放在AQS的等待队列里。
    private boolean findNodeFromTail(Node node) {
        Node t = tail;
        for (;;) {
            if (t == node)
                return true;
            if (t == null)
                return false;
            t = t.prev;
        }
    }

//AQS中的fullyRelease 该放方式是释放锁,包括重入锁的次数也全部释放完
      final int fullyRelease(Node node) {
        boolean failed = true;
        try {
			//拿到锁的状态
            int savedState = getState();
			//把重入的次数全部释放完
            if (release(savedState)) {
                failed = false;
                return savedState;
            } else {
                throw new IllegalMonitorStateException();
            }
        } finally {
            if (failed)
                node.waitStatus = Node.CANCELLED;
        }
    }

        
        final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
            return sync == AbstractQueuedSynchronizer.this;
        }

      //判断释放有条件等待节点
        protected final boolean hasWaiters() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    return true;
            }
            return false;
        }

      //获取队列长度
        protected final int getWaitQueueLength() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            int n = 0;
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION)
                    ++n;
            }
            return n;
        }

        //获取条件等待节点的线程
        protected final Collection<Thread> getWaitingThreads() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            ArrayList<Thread> list = new ArrayList<Thread>();
            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                if (w.waitStatus == Node.CONDITION) {
                    Thread t = w.thread;
                    if (t != null)
                        list.add(t);
                }
            }
            return list;
        }
    }