併發編程的兩個關鍵問題:程序員
1.線程之間如何通信。編程
2.線程間如何同步。數組
兩種方式:共享內存和消息傳遞。緩存
Java的併發採用的是共享內存模型,Java線程之間的通訊老是隱式進行,整個通訊過程對程序員徹底透明。
併發
實例域、靜態域和數組元素都存儲在堆內存中,堆內存在線程之間共享。Java線程之間的通訊由Java內存模型:JMM控制。app
JMM經過控制主內存與每一個線程的本地內存之間的交互,來爲Java程序員提供內存可見性保證 。優化
重排序分3種類型:
1)編譯器優化的重排序。編譯器在不改變單線程程序語義的前提下,能夠從新安排語句的執行順序。
2)指令級並行的重排序。現代處理器採用了指令級並行技術(Instruction-LevelParallelism,ILP)來將多條指令重疊執行。若是不存在數據依賴性,處理器能夠改變語句對應機器指令的執行順序。
3)內存系統的重排序。因爲處理器使用緩存和讀/寫緩衝區,這使得加載和存儲操做看上去多是在亂序執行 。spa
對於處理器重排序,JMM的處理器重排序規則會要求Java編譯器在生成指令序列時,插入特定類型的內存屏障(Memory Barriers,Intel稱之爲Memory Fence)指令,經過內存屏障指令來禁止特定類型的處理器重排序 。
線程
happens-before規則以下:
1.·程序順序規則:一個線程中的每一個操做,happens-before於該線程中的任意後續操做。
2.·監視器鎖規則:對一個鎖的解鎖,happens-before於隨後對這個鎖的加鎖。
3.·volatile變量規則:對一個volatile域的寫,happens-before於任意後續對這個volatile域的讀。
4.·傳遞性:若是A happens-before B,且B happens-before C,那麼A happens-before C。
blog
順序一致性,可見性保證。全部的操做按程序的順序執行,而JMM中臨界區內的代碼能夠重排序。
volatile寫的內存語義以下。
當寫一個volatile變量時,JMM會把該線程對應的本地內存中的共享變量值刷新到主內存。
volatile讀的內存語義以下。
當讀一個volatile變量時,JMM會把該線程對應的本地內存置爲無效。線程接下來將從主內存中讀取共享變量。
ReentrantLock:有公平鎖和非公平鎖
Java線程之間的通訊4種方式 1)A線程寫volatile變量,隨後B線程讀這個volatile變量。 2)A線程寫volatile變量,隨後B線程用CAS更新這個volatile變量。 3)A線程用CAS更新一個volatile變量,隨後B線程用CAS更新這個volatile變量。 4)A線程用CAS更新一個volatile變量,隨後B線程讀這個volatile變量