Java內存模型

  1. 爲什麼定義Java內存模型?現代計算機體系大部是採用的對稱多處理器的體系架構。每個處理器均有獨立的寄存器組和緩存,多個處理器可同時執行同一進程中的不同線程,這裏稱爲處理器的亂序執行。在Java中,不同的線程可能訪問同一個共享或共享變量。如果任由編譯器或處理器對這些訪問進行優化的話,很有可能出現無法想象的問題,這裏稱爲編譯器的重排序。除了處理器的亂序執行、編譯器的重排序,還有內存系統的重排序。因此Java語言規範引入了Java內存模型,通過定義多項規則對編譯器和處理器進行限制,主要是針對可見性和有序性。
  2. 三個基本原則:原子性、可見性、有序性。
  3. Java內存模型涉及的幾個關鍵詞:鎖、volatile字段、final修飾符與對象的安全發佈。其中:第一是鎖,鎖操作是具備happens-before關係的,解鎖操作happens-before之後對同一把鎖的加鎖操作。實際上,在解鎖的時候,JVM需要強制刷新緩存,使得當前線程所修改的內存對其他線程可見。第二是volatile字段,volatile字段可以看成是一種不保證原子性的同步但保證可見性的特性,其性能往往是優於鎖操作的。但是,頻繁地訪問 volatile字段也會出現因爲不斷地強制刷新緩存而影響程序的性能的問題。第三是final修飾符,final修飾的實例字段則是涉及到新建對象的發佈問題。當一個對象包含final修飾的實例字段時,其他線程能夠看到已經初始化的final實例字段,這是安全的。
  4. Happens-Before的7個規則:
    (1).程序次序規則:在一個線程內,按照程序代碼順序,書寫在前面的操作先行發生於書寫在後面的操作。準確地說,應該是控制流順序而不是程序代碼順序,因爲要考慮分支、循環等結構。
    (2).管程鎖定規則:一個unlock操作先行發生於後面對同一個鎖的lock操作。這裏必須強調的是同一個鎖,而"後面"是指時間上的先後順序。
    (3).volatile變量規則:對一個volatile變量的寫操作先行發生於後面對這個變量的讀操作,這裏的"後面"同樣是指時間上的先後順序。
    (4).線程啓動規則:Thread對象的start()方法先行發生於此線程的每一個動作。
    (5).線程終止規則:線程中的所有操作都先行發生於對此線程的終止檢測,我們可以通過Thread.join()方法結束、Thread.isAlive()的返回值等手段檢測到線程已經終止執行。
    (6).線程中斷規則:對線程interrupt()方法的調用先行發生於被中斷線程的代碼檢測到中斷事件的發生,可以通過Thread.interrupted()方法檢測到是否有中斷髮生。
    (7).對象終結規則:一個對象的初始化完成(構造函數執行結束)先行發生於它的finalize()方法的開始。
  5. Happens-Before的1個特性:傳遞性。
  6. Java內存模型底層怎麼實現的?主要是通過內存屏障(memory barrier)禁止重排序的,即時編譯器根據具體的底層體系架構,將這些內存屏障替換成具體的 CPU 指令。對於編譯器而言,內存屏障將限制它所能做的重排序優化。而對於處理器而言,內存屏障將會導致緩存的刷新操作。比如,對於volatile,編譯器將在volatile字段的讀寫操作前後各插入一些內存屏障。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章