av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

多線程 - 關(guān)于Java內(nèi)存可見(jiàn)性的問(wèn)題

瀏覽:127日期:2023-12-02 08:39:19

問(wèn)題描述

請(qǐng)看以下代碼

public class TestVolatile {public static void main(String[] args) throws InterruptedException {ThreadDemo td = new ThreadDemo();new Thread(td).start();Thread.sleep(1);while(true){ if(td.isFlag()){System.out.println('------------------');break; }} }}class ThreadDemo implements Runnable { private boolean flag = false; @Override public void run() {try { Thread.sleep(200);} catch (InterruptedException e) {}flag = true;System.out.println('flag=' + isFlag()); } public boolean isFlag() {return flag; } public void setFlag(boolean flag) {this.flag = flag; }}

把Thread.sleep(1)換成Thread.sleep(1000)就能獲取flag修改后的值,即td.isFlag()返回true。雖然看了Java內(nèi)存模型的概念,但我不知道如何解釋這段代碼,誰(shuí)能解釋一下?

相關(guān)問(wèn)題: Java多線程的工作內(nèi)存是什么?

問(wèn)題解答

回答1:

你得先說(shuō)說(shuō)你的預(yù)期效果是啥?問(wèn)問(wèn)題要問(wèn)清楚啊

回答2:

這個(gè)期待是沒(méi)有規(guī)范支撐的。代碼中沒(méi)有做任何能保證 '子線程寫 happen-before 主線程讀' 的事情。

sleep(1000)后看到修改只是巧合,一個(gè)JVM如果在更久后才讓主線程看到,甚至永遠(yuǎn)不讓主線程看到都不違反規(guī)范。

回答3:

你的程序應(yīng)該是想測(cè)試 volatile 關(guān)鍵字的功能。但是 “把 Thread.sleep(1) 換成 Thread.sleep(1000) 就能獲得預(yù)期效果” 這樣做理解上是不對(duì)的。首先,程序中總共有兩個(gè)線程,主線程(暫稱 線程M)和 new Thread(td) (暫稱 線程T)。

當(dāng)寫 Thread.sleep(1) 的時(shí)候,線程M 在 1ms 之后,便開(kāi)始在 while(true) 循環(huán)中檢查 td.isFlag() 的值,但是因?yàn)閮?nèi)存可見(jiàn)性的關(guān)系,線程M 并不能及時(shí)讀取 線程T 中 flag 的值,所以此時(shí)導(dǎo)致了死循環(huán);

當(dāng)寫 Thread.sleep(1000) 的時(shí)候,M 在 1000ms 之后,開(kāi)始在 while(true) 循環(huán)中檢查 td.isFlag() 的值;但是 T 在 200ms 的時(shí)候,便將 flag 的值設(shè)為 true 了,所以,M 在 1000ms 之后檢測(cè) td.isFlag() 的值肯定是返回 true 的,那么第一次判斷便會(huì)返回 true,產(chǎn)生輸出并跳出 while(true) 循環(huán)。

為了讓 線程M 及時(shí)讀取到 線程T 中 flag 的值,需要將 flag 使用 volatile 關(guān)鍵字進(jìn)行修飾:

private volatile boolean flag = false;

那么每次對(duì) flag 的修改,其他線程都立馬可見(jiàn)。關(guān)于 volatile 的使用,可以參考我的博客:Java 多線程(6):volatile 關(guān)鍵字的使用

回答4:

可以參考如下三個(gè)代碼:其中第一個(gè)和你的情況一樣,由于多線程的可見(jiàn)性問(wèn)題,可能導(dǎo)致無(wú)限循環(huán)下去。第二個(gè)是使用synchronized解決此問(wèn)題,大多數(shù)工作場(chǎng)景用這個(gè)好第三個(gè)是使用volatile解決,但這個(gè)關(guān)鍵字只保證可見(jiàn)性,在實(shí)際場(chǎng)景中局限性比較大,得慎用

public class StopThread {private static boolean stopRequested;public static void main(String[] args) throws InterruptedException {Thread backgroundThread = new Thread(new Runnable() {@Override public void run() {@SuppressWarnings('unused')int i = 0;while(!stopRequested) {// System.out.println('加上這一句程序就可以終止,否則無(wú)限循環(huán)下去'); i++;} }});backgroundThread.start();TimeUnit.SECONDS.sleep(1);stopRequested = true; }}

public class StopThread2 {private static boolean stopRequested;public static synchronized boolean getStopRequested() {return stopRequested; }public static synchronized void requestStop() {stopRequested = true; }public static void main(String[] args) throws InterruptedException {Thread backgroundThread = new Thread(new Runnable() {@Override public void run() {@SuppressWarnings('unused')int i = 0;while(!getStopRequested()/* stopRequested */) { i++;} }});backgroundThread.start();TimeUnit.SECONDS.sleep(1);requestStop();/* stopRequested = true; */ }}

public class StopThread3 {private static volatile boolean stopRequested; public static void main(String[] args) throws InterruptedException {Thread backgroundThread = new Thread(new Runnable() {@Override public void run() {@SuppressWarnings('unused')int i = 0;while(stopRequested) { i++;} }});backgroundThread.start();TimeUnit.SECONDS.sleep(1);stopRequested = true; }}

標(biāo)簽: java
相關(guān)文章:
主站蜘蛛池模板: 欧美日韩91 | 日本熟妇毛耸耸xxxxxx | 999久久久 | 亚洲天堂免费视频 | 欧美久久精品 | 黄av在线| 日韩精品福利 | 亚洲成人免费在线 | 美女国产精品 | 国产免费黄色片 | 国产午夜激情 | av在线免费播放 | 91av在线看| 成人三级视频在线观看 | 国产日韩在线播放 | 亚洲综合第一页 | 中文字幕亚洲一区 | 成年人视频在线免费观看 | 躁躁躁日日躁 | 美女毛片视频 | 日本www色 | 欧美成人极品 | 国产欧美日韩一区二区三区 | 成人精品免费视频 | 日韩天天操 | 国产日韩精品一区二区 | 亚洲综合国产 | 亚洲国产精 | 亚洲精品观看 | 黄在线免费观看 | 色在线播放 | 午夜在线观看视频 | 黄色一级视频免费看 | 国产三级在线 | 8090理论片午夜理伦片 | 日本不卡一区二区 | 91青青草 | 激情视频一区 | 成人免费毛片嘿嘿连载视频 | 91女人18毛片水多国产 | 中文字幕一区二区三区在线观看 |