一、並發編程兩個關鍵問題
線程之間如何通信、同步。java並發采用的是共享內存模型
二、JMM內存模型的抽象結構
描述的是一組規則或規范,通過這組規范定義了程序中各個變量(包括實例字段,靜態字段和構成數組對象的元素)的訪問方式。
JMM決定一個線程對共享變量的寫入何時對另一個線程可見。
JMM定義了線程和主內存之間的抽象關系:線程之間的共享變量存儲在主內存(Main Memory)中,每個線程都有一個私有的本地內存(Local Memory),本地內存中存儲了該線程讀/寫共享變量的副本。

如果線程A與線程B之間要通信的話,必須要經歷下面2個步驟。
1)線程A把本地內存A中更新過的共享變量刷新到主內存中去。
2)線程B到主內存中去讀取線程A之前已更新過的共享變量。
三、JMM內存模型三大特性
1、原子性
- AtomicInteger
- 使用 synchronized 互斥鎖來保證操作的原子性
2、可見性:
- volatile,會強制將該變量自己和當時其他變量的狀態都刷出緩存。
- synchronized,對一個變量執行 unlock 操作之前,必須把變量值同步回主內存。
- final,被 final 關鍵字修飾的字段在構造器中一旦初始化完成,並且沒有發生 this 逃逸(其它線程通過 this 引用訪問到初始化了一半的對象),那么其它線程就能看見 final 字段的值。
3、有序性
源代碼 -> 編譯器優化的重排 -> 指令並行的重排 -> 內存系統的重排 ->最終執行的命令
重排序過程不會影響到單線程程序的執行,卻會影響到多線程並發執行的正確性
處理器在進行重排時必須考慮數據的依賴性,多線程環境線程交替執行,由於編譯器優化重排的存在,兩個線程中使用的變量能否保證一致性是無法確定的。
1)編譯器優化的重排:
編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執行順序。

2)指令並行的重排
如果不存在數據依賴性,處理器可以改變語句對應機器指令的執行順序。
3)內存系統的重排
由於處理器使用緩存和讀/寫緩沖區,這使得加載和存儲操作看上去可能是在亂序執行。
- volatile 關鍵字通過添加內存屏障(Memory Barriers)的方式來禁止特定類型的處理器重排序,即重排序時不能把后面的指令放到內存屏障之前。
- synchronized 保證每個時刻只有一個線程執行同步代碼,相當於是讓線程順序執行同步代碼。
