java Condtion await方法和signal方法解析

public final void await() throws InterruptedException {
           //线程已经中断抛出异常
	    if (Thread.interrupted())
                throw new InterruptedException();
	   //加入队列同时清理队列中状态不是Node.CONDITION的线程
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            int interruptMode = 0;
	    //判断当前node是否在lock的队列中
            while (!isOnSyncQueue(node)) {
	      //不在sync队列中,挂起。
                LockSupport.park(this);
		//判断线程是否被中断
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
	    //在队列中阻塞等待
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
	   //清除队列中不是condition值的node。
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();
	   //对中断的响应
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }


  /**
   这段代码是将node入队。
   1、当队列为空的时候初始化firstWaiter和lastWaiter并且firstWaiter=lastWaiter.
   2、当队列不为空的是时候, t.nextWaiter = node;同时更新了firstWaiter和lastWaiter的nextWaiter.
    lastWaiter = node;将尾节点指向新加入的node。
   3、这个地方关键在于lastWaiter和队列中的最后一个nextWaiter持有相同的引用.
  */
  private Node addConditionWaiter() {
            //指向最后一个节点
            Node t = lastWaiter;
            //从最后个节点开始查找,将waitStatus不等于Node.CONDITION的清除出队列。
            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;
        }


 //将waitStatus不等于Node.CONDITION的清除出队列。
 private void unlinkCancelledWaiters() {
            Node t = firstWaiter;
            Node trail = null;
            while (t != null) {
                Node next = t.nextWaiter;
                if (t.waitStatus != Node.CONDITION) {
                    t.nextWaiter = null;
                    if (trail == null)
                        firstWaiter = next;
                    else
                        trail.nextWaiter = next;
                    if (next == null)
                        lastWaiter = trail;
                }
                else
                    trail = t;
                t = next;
            }
        }

   //释放锁
    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;
        }
    }

   //判断该节点是否在sync队列中。
    final boolean isOnSyncQueue(Node node) {
       //只有condition中node的waitStatus才会等于CONDITION。condition中的node也没有prev
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
       //如果node存在next节点那么肯定在sync队列中
        if (node.next != null) // If has successor, it must be on queue
            return true;
        /*
         node.prev可能不为空但是还没有进入到队列中,因为CAS执行可能会失败。所以继续检查。
         */
        return findNodeFromTail(node);
    }
   
   //从队尾开始从前遍历检查该node是否在sync队列中。
    private boolean findNodeFromTail(Node node) {
        Node t = tail;
        for (;;) {
            if (t == node)
                return true;
            if (t == null)
                return false;
            t = t.prev;
        }
    }

     
     private int checkInterruptWhileWaiting(Node node) {
            return Thread.interrupted() ?
	        //线程被中断了
                (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
                0;
        }
    
    final boolean transferAfterCancelledWait(Node node) {
       //将node的值设置为0然后加入sync队列
        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
	   //入队
            enq(node);
            return true;
        }
        /*
         如果没有在sync队列中自旋。
         */
        while (!isOnSyncQueue(node))
            Thread.yield();
        return false;
    }

     private void reportInterruptAfterWait(int interruptMode)
            throws InterruptedException {
            if (interruptMode == THROW_IE)
                throw new InterruptedException();
            else if (interruptMode == REINTERRUPT)
                selfInterrupt();
        }


 //再来看 signal()方法
 public final void signal() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
	    //对第一个节点进行移出condition队列加入sync队列的操作。
            if (first != null)
                doSignal(first);
        }


 private void doSignal(Node first) {
            do {
                if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                first.nextWaiter = null;
            } while (!transferForSignal(first) &&
                     (first = firstWaiter) != null);
        }


final boolean transferForSignal(Node node) {
        /*
         * 将node的状态设置为0.
         */
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;

        /*
         * Splice onto queue and try to set waitStatus of predecessor to
         * indicate that thread is (probably) waiting. If cancelled or
         * attempt to set waitStatus fails, wake up to resync (in which
         * case the waitStatus can be transiently and harmlessly wrong).
         */
	//加入sync队列
        Node p = enq(node);
        int ws = p.waitStatus;
	//如果当前线程的状态是cancel挂起当前线程
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            LockSupport.unpark(node.thread);
        return true;
    }

    /**总结:condition的await方法会释放锁,然后挂起直到被加入sync队列。而signal方法则是
    在condition队列中移出firstWaiter,然后将其加入sync队列。
    最后在unlock()方法唤醒线程。
    */


猜你喜欢

转载自chen-sai-201607223902.iteye.com/blog/2387743