Java虛擬機-常見的內存語義的分析

1.鎖的釋放與獲取所建立的happens-before關係:
public class Demo {
    private int value;

    public synchronized void a() {
        value++;  //1
    } 

    public synchronized void b() {
        int a = value;  //2
    } 
}

根據volatile變量規則,1happens-before2。

鎖的獲取和釋放的內存語義:鎖除了讓臨界區互斥執行外,還可以讓釋放鎖的線程向獲取同一個鎖的線程發送消息。

2.volatile的內存語義

volatile讀寫所建立的happens-before關係:
public class Demo {

    private volatile int a;

    private volatile boolean flag;

    public void writer() {
        a = 1; //1
        flag = true; //2
    }

    public void reader() {
        if (flag) { //3
            int b = a + 1; //4
            System.out.println(a); //5
        }
    }
}

根據程序順序性規則,1happens-before2,3happens-before4,4happnes-before5。根據volatile變量規則,2happens-before3。根據傳遞性規則,1happens-before4。

volatile讀寫的內存語義:當一個線程對volatile的變量進行寫操作時Java的內存模型會將該線程對應的本地內存的共享變量刷新到主內存中去。當一個線程讀一個volatile變量時,Java內存模型會把當前線程對應的本地內存中的共享變量置爲無效,然後從主內存中重新讀取該共享變量。

3.final的內存語義

寫final域的重排序規則:    寫final域的重排序規則禁止把final域的寫重排序到構造方法之外。Java的內存模型禁止編譯器把final域的寫重排序到構造方法之外。編譯器會在final域的寫之後,在構造方法執行完畢之前,插入一個內存屏障StoreStore,保證處理器把final域的寫操作在構造方法中執行。處理器通過內存屏障來禁止把final域的寫重排序到構造方法之外。LoadLoad、StoreStore、LoadStore、StoreLoad屏障。
public class Demo {
    
    private int a;

    private final int b;

    public Demo {
        b = 10;
    }
}

讀final域的重排序規則:在一個線程中,初次讀對象引用和初次讀該對象所包含的final域,Java內存模型禁止處理器重排序這兩個操作。

final域爲靜態類型:final域的初始化只在類加載時執行一次,類加載保證線程安全。

fianl域爲抽象類型:在構造方法內對一個final引用的對象的成員域的寫入,與隨後在構造方法外把這個被構造對象的引用賦值給一個引用變量,這兩個操作之間不能重排序。

public class Demo {
    
    private final Object obj;

    public Demo() {
        obj = new Object(); // 1
    }

    private Demo demo;

    private void w() {
        demo = new Demo();
    }

    public void r() {
        Demo d = demo; //2
    }
}

1和2不能重排序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章