Java內(nèi)存模型指定了JVM和計(jì)算機(jī)內(nèi)存是如何進(jìn)行協(xié)作
Java內(nèi)存模型的原理
Java內(nèi)存被分為線程棧和堆
棧:JVM中的每個(gè)線程擁有一個(gè)自己的線程棧,線程棧中包含當(dāng)前調(diào)用方法的信息,所有被調(diào)用方法的本地變量。
堆:java應(yīng)用程序中的所有對(duì)象,與線程無關(guān)。

JVM內(nèi)存模型
- 局部變量==>棧==>線程安全
- 局部對(duì)象==>引用在棧,對(duì)象在堆==>可能安全
- 對(duì)象方法里面的局部變量==>對(duì)象在堆,局部變量在棧==>線程安全
- 對(duì)象里面的成員變量==>堆==>線程不安全
- 靜態(tài)類==>堆==>線程不安全
public class MyRunnable implements Runnable() {
public void run() {
methodOne();
}
public void methodOne() {
int localVariable1 = 45;
MySharedObject localVariable2 =
MySharedObject.sharedInstance;
//... do more with local variables.
methodTwo();
}
public void methodTwo() {
Integer localVariable1 = new Integer(99);
//... do more with local variable.
}
}
public class MySharedObject {
//static variable pointing to instance of MySharedObject
public static final MySharedObject sharedInstance =
new MySharedObject();
//member variables pointing to two objects on the heap
public Integer object2 = new Integer(22);
public Integer object4 = new Integer(44);
public long member1 = 12345;
public long member1 = 67890;
}
硬件內(nèi)存架構(gòu)

電腦硬件架構(gòu)
- 一個(gè)現(xiàn)代計(jì)算機(jī)通常由兩個(gè)或者多個(gè)CPU。其中一些CPU還有多核。
- 每個(gè)CPU都包含一系列的寄存器,它們是CPU內(nèi)存的基礎(chǔ)。
- 每個(gè)CPU可能還有一個(gè)CPU緩存層。CPU訪問緩存層的速度快于訪問主存的速度,但通常比訪問內(nèi)部寄存器的速度還要慢一點(diǎn)。
- 一個(gè)計(jì)算機(jī)還包含一個(gè)主存。所有的CPU都可以訪問主存。主存通常比CPU中的緩存大得多。
- 通常情況下,當(dāng)一個(gè)CPU需要讀取主存時(shí),它會(huì)將主存的部分讀到CPU緩存中。它甚至可能將緩存中的部分內(nèi)容讀到它的內(nèi)部寄存器中,然后在寄存器中執(zhí)行操作。當(dāng)CPU需要將結(jié)果寫回到主存中去時(shí),它會(huì)將內(nèi)部寄存器的值刷新到緩存中,然后在某個(gè)時(shí)間點(diǎn)將值刷新回主存。
Java內(nèi)存模型和硬件內(nèi)存架構(gòu)之間的橋接
共享對(duì)象的可見性
如果兩個(gè)或者更多的線程在沒有正確的使用volatile聲明或者同步的情況下共享一個(gè)對(duì)象,一個(gè)線程更新這個(gè)共享對(duì)象可能對(duì)其它線程來說是不接見的。

共享對(duì)象的可見性
可以使用volatile關(guān)鍵字解決這個(gè)問題
race condition
如果兩個(gè)或者更多的線程共享一個(gè)對(duì)象,多個(gè)線程在這個(gè)共享對(duì)象上更新變量,就有可能發(fā)生race conditions。

更新變量發(fā)生 race condition
可以使用同步塊解決這個(gè)問題