国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

關(guān)于一個(gè)可見(jiàn)性和指令重排序的例子

2019-11-10 22:52:24
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

java cocurrency in PRactice

public class NoVisibility { private static boolean ready; private static int number; private static class ReaderThread extends Thread{ public void run(){ while (!ready) { System.out.println(3); // Thread.yield(); } System.out.println(number); } } public static void main(String args[]) throws Exception{ new ReaderThread().start(); //Thread.sleep(1000);//2 number=42;//1 ready=true;//1 }}

書中說(shuō)可能會(huì)持續(xù)循環(huán)下去(看不到ready的新值,可見(jiàn)性), 也有可能輸出0(指令重排序)。

可見(jiàn)性的問(wèn)題是由于ReaderThread線程可能會(huì)在工作內(nèi)存中緩存ready的值,在主線程更新完ready的值后,ReaderThread線程的工作內(nèi)存沒(méi)有得到刷新。

指令重排序的問(wèn)題時(shí)由于注釋1處兩行代碼由于編譯器、處理器或Runtime的優(yōu)化,可能會(huì)發(fā)生顛倒,導(dǎo)致ReaderThread線程讀到了ready新值,此時(shí)卻沒(méi)有讀到number的新值。

但是在實(shí)際運(yùn)行時(shí),發(fā)現(xiàn)根本不會(huì)發(fā)生死循環(huán),也不會(huì)輸出0。原因可能是在現(xiàn)代多核處理器計(jì)算機(jī)上,代碼中主線程啟動(dòng)完一個(gè)子線程后,主線程幾乎不會(huì)掛起而是繼續(xù)執(zhí)行,而新子線程的啟動(dòng)又是需要一段時(shí)間的,所以代碼1中的指令總是先于新子線程的代碼。

因此,我在注釋2處讓主線程掛起1秒,確保子線程已經(jīng)啟動(dòng)完成,即保證注釋1代碼晚于子線程代碼執(zhí)行。按理說(shuō)此時(shí)ready變量不是volatile類型,主線程更新完ready的值后子線程應(yīng)該看不到才對(duì),因此一直輸出3,但是在實(shí)際執(zhí)行代碼時(shí),運(yùn)行結(jié)果卻是程序正常退出,并且輸出number的新值42。按照網(wǎng)上說(shuō)法,可能是jdk自身優(yōu)化了代碼,導(dǎo)致子線程可以看到主線程更新的ready新值。

雖然說(shuō)實(shí)際運(yùn)行代碼時(shí)沒(méi)有出現(xiàn)可見(jiàn)性或指令重排序的問(wèn)題,但這并不表明代碼是正確的,程序仍然后風(fēng)險(xiǎn)存在,要確保程序表現(xiàn)出正確性,成為線程安全的,還是需要使用volatile變量。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 无锡市| 康平县| 丘北县| 阿拉尔市| 新田县| 广南县| 云霄县| 木里| 张家界市| 那曲县| 奉贤区| 铁力市| 安泽县| 本溪| 苗栗县| 双牌县| 黄浦区| 合山市| 扶余县| 大足县| 汾西县| 庆元县| 谷城县| 习水县| 新沂市| 临江市| 东莞市| 扶风县| 本溪| 富民县| 和田市| 滕州市| 平远县| 易门县| 牡丹江市| 芒康县| 会泽县| 淳化县| 炉霍县| 布尔津县| 嘉黎县|