亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

循環完成后程序未終止

循環完成后程序未終止

守候你守候我 2024-01-17 17:08:40
在以下場景中,布爾值“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的時間,這也足以讓線程被告知完成變量更改。


查看完整回答
反對 回復 2024-01-17
?
四季花海

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


查看完整回答
反對 回復 2024-01-17
  • 2 回答
  • 0 關注
  • 177 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號