java await signal_java Condtion await方法和signal方法解析
public final void await() throws InterruptedException {
//線程已經(jīng)中斷拋出異常
if (Thread.interrupted())
throw new InterruptedException();
//加入隊(duì)列同時(shí)清理隊(duì)列中狀態(tài)不是Node.CONDITION的線程
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
int interruptMode = 0;
//判斷當(dāng)前node是否在lock的隊(duì)列中
while (!isOnSyncQueue(node)) {
//不在sync隊(duì)列中,掛起。
LockSupport.park(this);
//判斷線程是否被中斷
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
//在隊(duì)列中阻塞等待
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
//清除隊(duì)列中不是condition值的node。
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
//對(duì)中斷的響應(yīng)
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
/**
這段代碼是將node入隊(duì)。
1、當(dāng)隊(duì)列為空的時(shí)候初始化firstWaiter和lastWaiter并且firstWaiter=lastWaiter.
2、當(dāng)隊(duì)列不為空的是時(shí)候, t.nextWaiter = node;同時(shí)更新了firstWaiter和lastWaiter的nextWaiter.
lastWaiter = node;將尾節(jié)點(diǎn)指向新加入的node。
3、這個(gè)地方關(guān)鍵在于lastWaiter和隊(duì)列中的最后一個(gè)nextWaiter持有相同的引用.
*/
private Node addConditionWaiter() {
//指向最后一個(gè)節(jié)點(diǎn)
Node t = lastWaiter;
//從最后個(gè)節(jié)點(diǎn)開(kāi)始查找,將waitStatus不等于Node.CONDITION的清除出隊(duì)列。
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的清除出隊(duì)列。
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;
}
}
//判斷該節(jié)點(diǎn)是否在sync隊(duì)列中。
final boolean isOnSyncQueue(Node node) {
//只有condition中node的waitStatus才會(huì)等于CONDITION。condition中的node也沒(méi)有prev
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
//如果node存在next節(jié)點(diǎn)那么肯定在sync隊(duì)列中
if (node.next != null) // If has successor, it must be on queue
return true;
/*
node.prev可能不為空但是還沒(méi)有進(jìn)入到隊(duì)列中,因?yàn)镃AS執(zhí)行可能會(huì)失敗。所以繼續(xù)檢查。
*/
return findNodeFromTail(node);
}
//從隊(duì)尾開(kāi)始從前遍歷檢查該node是否在sync隊(duì)列中。
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的值設(shè)置為0然后加入sync隊(duì)列
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
//入隊(duì)
enq(node);
return true;
}
/*
如果沒(méi)有在sync隊(duì)列中自旋。
*/
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();
}
//再來(lái)看 signal()方法
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
//對(duì)第一個(gè)節(jié)點(diǎn)進(jìn)行移出condition隊(duì)列加入sync隊(duì)列的操作。
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的狀態(tài)設(shè)置為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隊(duì)列
Node p = enq(node);
int ws = p.waitStatus;
//如果當(dāng)前線程的狀態(tài)是cancel掛起當(dāng)前線程
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
/**總結(jié):condition的await方法會(huì)釋放鎖,然后掛起直到被加入sync隊(duì)列。而signal方法則是
在condition隊(duì)列中移出firstWaiter,然后將其加入sync隊(duì)列。
最后在unlock()方法喚醒線程。
*/
分享到:
2017-07-31 13:48
瀏覽 165
分類:互聯(lián)網(wǎng)
評(píng)論
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的java await signal_java Condtion await方法和signal方法解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java视频流传输_java – 使用X
- 下一篇: java new thread参数_ja