學習筆記 變量定義在靜態塊輸出之後 不能輸出的問題

 


public class Test
{
    static
    {
        i=0;
        System.out.println(i);//這句編譯器會報錯:Cannot reference a field before it is defined(非法向前應用)
    }

    static int i=3;

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

}爲何在靜態塊時輸出時會報錯的原因。其實這個時候i已經分配好內存並賦值爲3了,由下面代碼可以證明。先運行實例化對象,再輸出類對象的參數成功。

public class statictest {         
    static{ 
        b=3;
      } 

    static statictest st = new statictest(); 
        
    statictest()  {          
        system.out.println(b);     
    }         

    public static int b=10;   
      
    public static void main(String[] args) {
  
} 

}


load(載入):作用於工作內存的變量,它把read操作從主內存中得到的變量值放入工作內存的變量副本中。

  • assign(賦值):作用於工作內存的變量,它把一個從執行引擎接收到的值賦給工作內存的變量,每當虛擬機遇到一個給變量賦值的字節碼指令時執行這個操作。

問題在於java內存模型,不允許一個工作內存中直接使用一個未被初始化的變量,當開始b申請了空間初始化爲0後,在類加載的初始化階段,順序執行靜態語句時候,已經將b=0從主內存複製到了工作內存,執行b=3 (修改工作內存),不允許一個線程丟棄它的最近的assign操作,即變量在工作內存中改變了之後必須把該變化同步回主內存。但是沒有完成提交到主內存完成assign和從主內存讀load操作,故輸出錯誤。但是在執行內實例化前,會將工作內存中所有數據同步到主內存,故滿足了規則一個新的變量只能在主內存中“誕生”,不允許在工作內存中直接使用一個未被初始化(load或assign)的變量,換句話說,就是對一個變量實施use、store操作之前,必須先執行過了assign和load操作。

8種基本操作規則:

  • 不允許read和load、store和write操作之一單獨出現,即不允許一個變量從主內存讀取了但工作內存不接受,或者從工作內存發起回寫了但主內存不接受的情況出現。
  • 不允許一個線程丟棄它的最近的assign操作,即變量在工作內存中改變了之後必須把該變化同步回主內存。
  • 不允許一個線程無原因地(沒有發生過任何assign操作)把數據從線程的工作內存同步回主內存中。
    • 一個新的變量只能在主內存中“誕生”,不允許在工作內存中直接使用一個未被初始化(load或assign)的變量,換句話說,就是對一個變量實施use、store操作之前,必須先執行過了assign和load操作。
  • 一個新的變量只能在主內存中“誕生”,不允許在工作內存中直接使用一個未被初始化(load或assign)的變量,換句話說,就是對一個變量實施use、store操作之前,必須先執行過了assign和load操作。
  • 一個變量在同一個時刻只允許一條線程對其進行lock操作,但lock操作可以被同一條線程重複執行多次,多次執行lock後,只有執行相同次數的unlock操作,變量纔會被解鎖。
  • 如果對一個變量執行lock操作,那將會清空工作內存中此變量的值,在執行引擎使用這個變量前,需要重新執行load或assign操作初始化變量的值。
  • 如果一個變量事先沒有被lock操作鎖定,那就不允許對它執行unlock操作,也不允許去unlock一個被其他線程鎖定住的變量。
  • 對一個變量執行unlock操作之前,必須先把此變量同步回主內存中(執行store、write操作)。

這8種內存訪問操作以及上述規則限定,再加上稍後介紹的對volatile的一些特殊規定,就已經完全確定了Java程序中哪些內存訪問操作在併發下是安全的。由於這種定義相當嚴謹但又十分煩瑣,實踐起來很麻煩,所以在後文將介紹這種定義的一個等效判斷原則——先行發生原則,用來確定一個訪問在併發環境下是否安全。

注: 
基於理解難度和嚴謹性考慮,最新的JSR-133文檔中,已經放棄採用這8種操作去定義Java內存模型的訪問協議了(僅是描述方式改變了,Java內存模型並沒有改變)。

 

發佈了34 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章