在以下場景中,布爾值“done”被設置為 true,這應該結束程序。相反,即使 while(!done) 不再是有效場景,程序也會繼續運行,因此它應該停止?,F在,如果我要添加線程睡眠,即使睡眠時間為零,程序也會按預期終止。這是為什么?public class Sample { private static boolean done; public static void main(String[] args) throws InterruptedException { done = false; new Thread(() -> { System.out.println("Running..."); int count = 0; while (!done) { count++; try { Thread.sleep(0); // program only ends if I add this line. } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); Thread.sleep(2000); done = true; // this is set to true after 2 seconds so program should end. System.out.println("Done!"); // this gets printed after 2 seconds }}編輯:我想了解為什么上面需要 Thread.sleep(0) 來終止。我不想使用 volatile 關鍵字,除非它是絕對必須的,并且我確實明白,通過將我的值暴露給所有線程(這不是我打算公開的)可以工作。
2 回答

HUX布斯
TA貢獻1876條經驗 獲得超6個贊
每個線程都為性能創建了不同的已緩存版本的did,您的計數器線程太忙于進行計數計算,以至于沒有機會重新加載did。
易失性確保任何讀/寫都在主內存上完成,始終更新 cpu 緩存副本。
Thread.sleep 總是暫停當前線程,因此即使 0 你的計數器線程被中斷一段<1ms的時間,這也足以讓線程被告知已完成變量更改。

四季花海
TA貢獻1811條經驗 獲得超5個贊
我不是 Java 專家,我什至不會用 Java 編程,但讓我嘗試一下。
Java 語言規范第 17 章定義了內存操作(例如共享變量的讀寫)的happens-before關系。僅當寫入操作發生在讀取操作之前時,才保證一個線程的寫入結果對另一線程的讀取可見。同步和易失性構造以及Thread.start()和Thread.join()方法可以形成happens-before關系。
如果您瀏覽該線程,它會提到執行共享變量的線程時的“發生在”邏輯。所以我的猜測是,當您調用 Thread.sleep(0) 時,主線程能夠正確設置 did 變量,確保它“首先發生”。但是,在多線程環境中,甚至不能保證這一點。但由于代碼片段非常小,因此在這種情況下仍然可以工作。
總而言之,我只是運行了您的程序,并對變量“done”進行了微小的更改,并且該程序按預期工作:
private?static?volatile?boolean?done;
謝謝。也許其他人可以給你更好的解釋:P
添加回答
舉報
0/150
提交
取消