Java並發(二):重排序
阿新 • • 發佈:2018-11-02
技術分享 安排 通過 mage 種類 操作 處理器 加載 str
在執行程序時為了提高性能,提高並行度,編譯器和處理器常常會對指令做重排序。重排序分三種類型:
- 編譯器優化的重排序。編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執行順序。
- 指令級並行的重排序。現代處理器采用了指令級並行技術(Instruction-Level Parallelism, ILP)來將多條指令重疊執行。如果不存在數據依賴性,處理器可以改變語句對應機器指令的執行順序。
- 內存系統的重排序。由於處理器使用緩存和讀/寫緩沖區,這使得加載和存儲操作看上去可能是在亂序執行。
問題:重排序都可能會導致多線程程序出現內存可見性問題
1)編譯器優化的重排序。編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執行順序。
2)指令級並行的重排序。處理器多條指令重疊執行,改變語句對應機器指令的執行順序(處理器重排)
3)內存系統的重排序。處理器使用緩存和讀/寫緩沖區,這使得加載和存儲操作看上去可能是在亂序執行(處理器重排)
舉例:處理器對內存的讀/寫操作的執行順序,不一定與內存實際發生的讀/寫操作順序一致,導致重排序導致內存可見性問題
(處理器使用寫緩沖區來臨時保存向內存寫入的數據:避免由於處理器停頓下來等待向內存寫入數據而產生的延遲
以批處理的方式刷新寫緩沖區,以及合並寫緩沖區中對同一內存地址的多次寫,可以減少對內存總線的占用)
假設處理器A和處理器B按程序的順序並行執行內存訪問,最終卻可能得到x = y = 0的結果
第一步執行A1 B1
第二步執行A2 B2,此時已得到x=b=0 y=a=0
第三步執行A3 B3
執行完A3,A1才算執行完,A1 A2重排序了
JMM通過禁止特定類型的編譯器重排序和處理器重排序,為程序員提供一致的內存可見性保證
JMM的編譯器重排序規則會禁止特定類型的編譯器重排序
java編譯器在生成指令序列時,插入特定類型的內存屏障指令來禁止特定類型的處理器重排序
Java並發(二):重排序