1. 程式人生 > 其它 >深入瞭解多執行緒之可見性

深入瞭解多執行緒之可見性

最近在深入學習多執行緒的知識在此記錄一下
併發程式設計三大特性有:可見性,有序性,原子性

可見性驗證程式碼:

public class Visibility {
    private static /** volatile */ boolean flag = true;

    private static void m(){
        System.out.println("m start");
        while (flag){

        }
        System.out.println("m end");

    }
    public static void main(String[] args) throws Exception{

            new Thread(Visibility::m,"t1").start();

            Thread.sleep(1);

            flag = false;
    }

在這段程式碼中,按照正常的邏輯 m end 是應該會被列印的

但是因為多執行緒時,一個執行緒取到該值後有存在只讀取快取中的值內容的情況,就導致了程式會陷入死迴圈,而不會列印 m end的情況。
當然該情況不是每次都發生,可以多試幾次。
當加入了 volatile關鍵字後即可保證 每一次 flag的值都可以及時的被重新整理。

但是當 volatile 修飾物件時,將只保證物件引用的可見性,而不保證物件中屬性的可見性,程式碼如下:

public class Visibility02 {
    private static class A{
        boolean flag = true;
        void m(){
            System.out.println("m start");
            while (flag){}
            System.out.println("m end");
        }
    }

    private volatile static A a = new A();

    public static void main(String[] args) throws Exception{
        new Thread(a::m,"t1").start();
        Thread.sleep(1);
        a.flag = false;
    }

所以當我們想保證物件中的屬性的可見性時需要用volatile去修飾該屬性.