如代碼所示,locksupport.park()在執行緒t1中被呼叫了兩次。第一次LockSupport.park()后,主執行緒用t1.interrupt()喚醒執行緒t1,然后在t1呼叫thread.interrupted()清除執行緒的中斷狀態。但是 Locksupport.park() 不會再次掛起執行緒。奇怪的是,注釋掉 [log.debug("test.......")] 后,locksupport.park() 可以再次暫停執行緒。這是什么原因?
在此處輸入影像描述
在此處輸入影像描述
@Slf4j
public class Test08Park4 {
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
LockSupport.park();
/**
* With this log print, locksupport.park () cannot stop threads;
* If you comment this out, locksupport.park () can stop the thread
*/
log.debug("test.......");
Thread.interrupted();
LockSupport.park();
log.debug("finished...");
}
});
t1.start();
sleep(1000);
t1.interrupt();
}
}
如果不將 [log.debug("test.......")] 注釋掉,結果:
22:37:05.435 [Thread-0] DEBUG test.Test08Park4 - test.......
22:37:05.439 [Thread-0] DEBUG test.Test08Park4 - finished...
如果注釋 [log.debug("test.......")] 出來,結果:
//沒有什么
uj5u.com熱心網友回復:
閱讀檔案是基礎。
正如檔案所示,LockSupport.park()允許虛假回傳。換句話說,檔案字面意思是:
- 問:“為什么 park() 呼叫這么快就回傳了?”
- A:因為 JVM 喜歡它。
LockSupport 的鎖是執行緒全域的。每個執行緒只有一個信號量(LockSupport 稱之為“許可”),你不能多做也不能少做。基本上意味著,你的 JVM 中只有一個系統可以使用它,因為如果有兩個系統使用它,它們就會相互混淆。
正如檔案中所說:
用于創建鎖和其他同步類的基本執行緒阻塞原語。
這實質上意味著:你為什么要這樣做?如果您想要鎖定行為,請ReentrantLock從java.util.concurrent包中使用例如;這不是為你準備的,因此它有各種各樣的奇怪之處,例如park()允許虛假回報的規則。
很可能代碼 [A]由于某種原因log.debug最終呼叫,這意味著下一個呼叫立即回傳,或者 [B] 這是一個時間問題。不是“免費”的,許多日志框架“就地”運行,這意味著呼叫實際上是在磁盤和 fsyncs 上進行的,這意味著與您的平均非磁盤互動 java 指令(數百值得時間的指令)。這段時間足以讓調度程式飛過它,特別是考慮到“寫入磁盤”或“fsync”是一個自然的停止點(java中的執行緒是先發制人的,但如果你給調度程式一個暫停你的執行緒的借口,它通常會接受它)。LockSupport.unpark(ownThread)park()log.debuglog.debug
最后,檔案很清楚:您沒有得到“為什么”問題的答案。規范讓 JVM 自由支配,不必向您解釋為什么park()虛假回傳。因此,追查這種情況的原因沒有多大意義——即使你有答案,明天也可能有不同的原因。如果您的代碼無法處理 上的虛假回傳LockSupport.park(),則根據定義,您的代碼已損壞。即使你可以讓它在你的機器上作業,今天,在這個月相下,那也不能保證它明天能正常作業。
一旦你的代碼可以處理虛假回傳,弄清楚它為什么在這里虛假回傳就不再有趣了。因此,解決方案:正確處理虛假回報。或者,更有可能的是,不要將其用于鎖,使用對最終用戶更友好的東西。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513757.html
標籤:爪哇多线程
上一篇:使用多執行緒/多核行程防止抖動
