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

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

關于Java線程并發的一個小問題

關于Java線程并發的一個小問題

一只名叫tom的貓 2019-03-12 11:19:21
前段時間我在看Effective Java的時候,第10章-并發中有這樣一個講解:public class StopThread {    private static boolean stopRequested;        public static void main(String[] args) throws Exception {        Thread backgroundThread = new Thread(new Runnable(){            public void run() {                int i = 0;                while(!stopRequested) {                    i++;                }            }        });        backgroundThread.start();                TimeUnit.SECONDS.sleep(1);        stopRequested = true;    }    }書上說:“你可能期待這個程序運行大約一秒左右,之后主線程將stopRequested設置為true,使后臺線程的循環終止。但是在我的機器上,這個程序永遠不會終止:因為后臺線程永遠在循環!問題在于,由于沒有同步,就不能保證后臺線程何時‘看到’主線程對stopRequested得值所做的改變。沒有同步,虛擬機將這個代碼:while(!done)    i++;轉變成這樣:if(!done)    while(true)        i++;”這到底是什么意思呢?為什么沒有使用同步則后臺線程看不到stopRequested的變化呢?最主要的問題在于,這段代碼在我的機器上跑,貌似1秒就結束了。沒有出現書中說描述的情況。書上這么寫的原因是什么呢?為什么寫成書上的樣子就可以防止可見性問題的出現?希望各位大神幫忙看下,給小弟我講解講解。小弟我是個技術小白。
查看完整描述

3 回答

?
DIEA

TA貢獻1820條經驗 獲得超2個贊

在沒有使用同步手段的時候,當主線程對stopRequested作的修改時,不能確定backgroundThread什么時候能看到變量更改。
因為在代碼執行時,會將變量從內存加載到寄存器,如果沒有同步,如果另外一個線程(A)對變量的更改就無法刷新到另一個線程(B)中,因為B使用的是寄存器中的變量。如果使用了同步機制,比如synchonized,或者volitle,變量的更改就會立即同步,這樣訪問這個變量的多個線程就能理科看到了。
在這里,
剛開始執行時,backgroundThread將stopRequested從內存讀到寄存器
這里沒有使用同步手段,當main線程對stopRequested更新時,只是更新到內存,backgroundThread取到的還是寄存器中的值,所以不會停止。

查看完整回答
反對 回復 2019-04-22
?
阿晨1998

TA貢獻2037條經驗 獲得超6個贊

  1. 通過查詢資料,確實和樓主說的環境有關系,樓主可以參考:
    Does liveness failure that happened in concurrency exist in java 8

  2. main方法結束了,其它非后臺線程不會停止運行(我把和junitTest弄混了)


查看完整回答
反對 回復 2019-04-22
?
繁星coding

TA貢獻1797條經驗 獲得超4個贊

這段程序剛開始執行的時候是主線程線程先執行的,然后才是backgroundThread執行,由于給stopRequested變量賦值的時候,停了一秒,這個時候backgroundThread線程搶到了執行權,可能是這個原因吧 個人就建議 不對勿噴!??!

查看完整回答
反對 回復 2019-04-22
  • 3 回答
  • 0 關注
  • 590 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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