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

Multithreading - Soalan tentang keterlihatan memori Java
漂亮男人
漂亮男人 2017-05-17 10:06:58
0
4
1061

Sila lihat kod berikut

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;
    }

}

Letak Thread.sleep(1)換成Thread.sleep(1000)就能獲取flag修改后的值,即td.isFlag()返回true.
Walaupun saya telah membaca konsep model memori Java, saya tidak tahu bagaimana untuk mentafsir kod ini Siapa yang boleh menerangkannya?

Soalan berkaitan: Apakah memori kerja Java multi-threading?

漂亮男人
漂亮男人

membalas semua(4)
淡淡煙草味

Anda perlu beritahu saya dahulu apakah kesan jangkaan anda? Tanya soalan dengan jelas

滿天的星座

Jangkaan ini tidak disokong oleh piawaian. Tiada apa-apa yang dilakukan dalam kod untuk menjamin bahawa "tulisan subthread berlaku-sebelum utas utama dibaca".

sleep(1000)Melihat pengubahsuaian kemudian hanyalah satu kebetulan Jika JVM menunggu lebih lama untuk utas utama untuk melihatnya, atau tidak pernah membiarkan utas utama melihatnya, ia tidak melanggar spesifikasi.

劉奇

Program anda sepatutnya ingin menguji kefungsian kata kunci volatile. Tetapi "menggantikan Thread.sleep(1) dengan Thread.sleep(1000) akan mencapai kesan yang diingini" bukanlah pemahaman yang betul.
Pertama sekali, terdapat dua utas dalam atur cara, utas utama (secara sementara dipanggil utas M) dan Benang baru(td) (sementara dipanggil utas T). volatile 關(guān)鍵字的功能。但是 “把 Thread.sleep(1) 換成 Thread.sleep(1000) 就能獲得預(yù)期效果” 這樣做理解上是不對的。
首先,程序中總共有兩個線程,主線程(暫稱 線程M)和 new Thread(td) (暫稱 線程T)。


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


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


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

private volatile boolean flag = false;

那么每次對 flag 的修改,其他線程都立馬可見。關(guān)于 volatile


Apabila menulis Thread.sleep(1), thread M mula menyemak td.isFlag() dalam gelung while(true) selepas 1ms , tetapi disebabkan keterlihatan memori, utas M tidak dapat membaca nilai bendera dalam utas T dalam masa, jadi gelung tak terhingga disebabkan pada masa ini ??
??Apabila menulis Thread.sleep(1000), M mula menyemak td.isFlag() dalam gelung while(true) selepas 1000ms. code>; tetapi T menetapkan nilai flag kepada true pada 200ms, jadi M mengesan td.isFlag( selepas 1000ms ) mesti mengembalikan benar, maka penghakiman pertama akan mengembalikan true, menjana output dan melompat keluar daripada gelung while(true) code>. ??
??Untuk thread M membaca nilai flag dalam thread T dalam masa, flag perlu diubah suai dengan kata kunci volatile: ?? rrreee ??Kemudian setiap pengubahsuaian bendera akan kelihatan serta-merta kepada urutan lain. Mengenai penggunaan volatile, anda boleh rujuk blog saya: Java Multithreading (6): Penggunaan kata kunci yang tidak menentu ??
大家講道理

Anda boleh merujuk kepada tiga kod berikut:
Kod pertama adalah sama dengan situasi anda disebabkan masalah keterlihatan berbilang benang, ia mungkin menyebabkan gelung yang tidak terhingga.
Yang kedua ialah menggunakan disegerakkan untuk menyelesaikan masalah ini. Ini bagus untuk kebanyakan senario kerja synchronized解決此問題,大多數(shù)工作場景用這個好
第三個是使用volatileYang ketiga ialah menggunakan volatile untuk menyelesaikan masalah ini, tetapi kata kunci ini sahaja menjamin keterlihatan Dalam senario sebenar, hadnya agak besar, jadi gunakannya dengan berhati-hati

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("加上這一句程序就可以終止,否則無限循環(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;
    }
}
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan