java await signal_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()方法喚醒線程。
*/
分享到:
2017-07-31 13:48
瀏覽 165
分類:互聯網
評論
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的java await signal_java Condtion await方法和signal方法解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java视频流传输_java – 使用X
- 下一篇: java jlable添加gif,Jav