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()方法唤醒线程。 */
java Condtion await方法和signal方法解析
猜你喜欢
转载自chen-sai-201607223902.iteye.com/blog/2387743
今日推荐
周排行