CPU 內存模型
在講解 JAVA 內存模型之前,先了解 CPU 內存模型,因爲JAVA內存模型跟它是十分相似的。
圖中的 Core 就是一個 CPU。可以看得出:
- L1 和 L2 是每個CPU自己的高速緩存
- L3 是多個CPU之間共享緩存。
- 黃色的就是主內存。
- L1、L2、L3 的存儲的速度、以及存儲的東西逐漸減少。
- L1 和 L2 的緩存命中率均爲 80%
- 達到 L3 緩存的數據佔比 4% 左右。
JAVA 內存模型
可以看得出這個跟 CPU 內存時十分相似的。黃色部分 Memory 相當於 CPU 的 L3 緩存了。
同時也可以看到啊, Copy Memory 是拷貝過來的。也正因爲這個東西的存在,引出了變量的可見性問題。
可見性問題
class XXX {
private static int a = 0;
Thread threadA = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " a = " + a);
a = 1;
System.out.println(Thread.currentThread().getName() + " a = " + a);
}, "ThreadA");
Thread threadB = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " a = " + a);
a = 1;
System.out.println(Thread.currentThread().getName() + " a = " + a);
}, "ThreadB");
}
當 new 多個線程去修改 a 這個變量時,就會出現可見性問題。也就是 : thread-A :a ->1 。但是 thread-B 不一定讀到 a 就是1,可能還是 0 ;
重排序問題
簡單解釋:
java 在執行程序時,可能會對指令進行重排。也就是按照代碼順序:
b = 1;
x = a;
但是執行時可能會變成:
x = a;
b = 1;
源代碼到真正執行一般會經過:
源代碼 -> 編譯器重排序 -> 處理器重排序 -> 最終執行順序
但是呢!!! 重排序也不是無條件去重排序的。他必須遵循一個 happen-before 規則。