在執(zhí)行程序時(shí),為了提高性能,編譯器和處理器常常會(huì)對(duì)指令做重排序。
重排序分以下3種類型:
編譯器優(yōu)化的重排序:編譯器在不改變單線程程序語(yǔ)義的前提下,可以重新安排語(yǔ)句的執(zhí)行順序。
指令級(jí)并行的重排序:現(xiàn)代處理器采用了指令級(jí)并行技術(shù)來將多條指令重疊執(zhí)行。如果不存在數(shù)據(jù)依賴性,處理器可以改變語(yǔ)句對(duì)應(yīng)機(jī)器指令的執(zhí)行順序。
內(nèi)存系統(tǒng)的重排序:由于處理器使用緩存和讀/寫緩沖區(qū),這使得加載和存儲(chǔ)操作看上去可能是在亂序執(zhí)行。
從Java源代碼到最終實(shí)際執(zhí)行的指令序列,會(huì)分別經(jīng)歷下面3種重排序:
上述的1屬于編譯器重排序,2和3屬于處理器重排序。
這些重排序可能會(huì)導(dǎo)致多線程程序出現(xiàn)內(nèi)存可見性問題。對(duì)于編譯器,JMM的編譯器重排序規(guī)則會(huì)禁止特定類型的編譯器重排序(不是所有的編譯器重排序都要禁止)。
對(duì)于處理器重排序,JMM的處理器重排序規(guī)則會(huì)要求Java編譯器在生成指令序列時(shí),插入特定類型的內(nèi)存屏障(Memory Barriers,Intel稱之為Memory Fence)指令,通過內(nèi)存屏障指令來禁止特定類型的處理器重排序。
JMM屬于語(yǔ)言級(jí)的內(nèi)存模型,它確保在不同的編譯器和不同的處理器平臺(tái)之上,通過禁止特定類型的編譯器重排序和處理器重排序,為程序員提供一致的內(nèi)存可見性保證。
-----------本文摘自《java并發(fā)編程的藝術(shù)》