Java內存模型把Java虛擬機內部劃分為線程棧和堆。每個線程都有自己的線程棧。如下圖。
線程棧(Thread Stack):線程棧中存放了本地變量(線程執行過程中在方法內定義的變量,無論是基本類型還是引用類型)堆(Heap):堆上則存放Java程序中創建的所有對象,一個對象包含的成員變量跟隨對象一起存放在堆上

在多核CPU中,在同一時刻,可能每個CPU上邊都同時分別跑著一個線程。
對于理解Java內存模型和內存交互原理,只需要知道CPU內部有一個緩存即可。如下圖。

硬件內存架構沒有區分線程棧和堆。對于硬件,所有的線程棧和堆都分布在主內中。部分線程棧和堆可能有時候會出現在CPU緩存中和CPU內部的寄存器中。如下圖。

當對象和變量被存放在計算機中各種不同的內存區域中時,就可能會出現一些具體的問題。主要包括如下兩個方面:
線程對共享變量修改的可見性當讀,寫和檢查共享變量時出現競爭條件(race conditions)對于共享對象,多個CPU上的線程可以同時將其讀到CPU緩存中,然后修改這個對象。只要CPU緩存沒有被刷新會主存,對象修改后的版本對跑在其它CPU上的線程都是不可見的。這種方式可能導致每個線程擁有這個共享對象的私有拷貝,每個拷貝停留在不同的CPU緩存中。如下圖。 從本質上來講,這是CPU的自身速度優化,使最新的Java對象不能及時地在多個線程相互可見(一個特性的優化往往會對另一個特性造成缺口)

如果兩個線程同時將整型變量count讀到各自的CPU緩存中,并且同時對其執行+1操作,最后再將count寫會到內存中,最終count的值只會被+1,而不是+2,盡管執行了兩次+1操作。 
原文鏈接
新聞熱點
疑難解答