国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

多執(zhí)行緒 - 關(guān)於Java記憶體可見(jiàn)性的問(wèn)題
漂亮男人
漂亮男人 2017-05-17 10:06:58
0
4
1066

請(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記憶體模型的概念,但我不知道該如何解釋這段程式碼,誰(shuí)能解釋一下?

相關(guān)問(wèn)題: Java多執(zhí)行緒的工作記憶體是什麼?

漂亮男人
漂亮男人

全部回覆(4)
淡淡煙草味

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

滿(mǎn)天的星座

這個(gè)期待是沒(méi)有規(guī)範(fàn)支撐的。程式碼中沒(méi)有做任何能保證 "子執(zhí)行緒寫(xiě) happen-before 主執(zhí)行緒讀" 的事情。

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

劉奇

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


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


當(dāng)寫(xiě)Thread.sleep(1000) 的時(shí)候,M 在1000ms 之後,開(kāi)始在while(true) 循環(huán)中檢查td.isFlag() code> 的值;但是T 在200ms 的時(shí)候,便將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)flag

的值設(shè)為true 了,所以,M 在1000ms 之後檢測(cè)td.isFlag()的值肯定是回傳true 的,那麼第一次判斷便會(huì)回傳true,產(chǎn)生輸出並跳出while(true) 迴圈。

為了讓 執(zhí)行緒M 及時(shí)讀取到 執(zhí)行緒T 中 flag 的值,需要將 flagvolatile 使用

關(guān)鍵字進(jìn)行修飾:

private volatile boolean flag = false;
那麼每次對(duì) flagvolatile 的修改,其他線(xiàn)程都立刻可見(jiàn)。關(guān)於 的使用,可以參考我的部落格:Java 多執(zhí)行緒(6):volatile 關(guān)鍵字的使用??
大家講道理

可以參考以下三個(gè)程式碼:
其中第一個(gè)和你的情況一樣,由於多執(zhí)行緒的可見(jiàn)性問(wèn)題,可能導(dǎo)致無(wú)限循環(huán)下去。
第二個(gè)是使用synchronized解決此問(wèn)題,大多數(shù)工作場(chǎng)景用這個(gè)好synchronized解決此問(wèn)題,大多數(shù)工作場(chǎng)景用這個(gè)好
第三個(gè)是使用volatile第三個(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;
    }
}
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板