您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何深入理解Java多線程與并發框中重排序、屏障指令、as-if-serial規則,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
一、重排序
前篇文章已經講了Java內存模型和與其三個特性:原子性、可見性、有序性。但事實上,為了提升程序的執行性能,編譯器 和 處理器 常常會對程序指令序列進行 重排序。
重排序分為以下幾種:
編譯器優化重排序
處理器重排序
指令級并行重排序
內存系統重排序
fence
內存屏障(Memory Barrier,或稱為內存柵欄,Memory Fence)是一種CPU指令,用于控制特定條件下的重排序和內存可見性問題。Java編譯器也會根據內存屏障的規則在一定程度地禁止重排序。
重排序也不能毫無規則,否則語義就變得不可讀, as-if-serial語句 給重排序戴上緊箍咒,起到約束作用。
as-if-serial語句規定重排序要滿足以下兩個規則:
在單線程環境下不能改變程序執行的結果;
存在數據依賴關系代碼(指令)片段的不允許重排序。
比如下面的代碼:
int a = 1; // ① int b = 2; // ② int c = a + b; // 依賴于 ① 和 ② return c;
可能會被優化成:
int b = 2; // ② int a = 1; // ① int c = a + b; // 依賴于 ① 和 ② return c;
上述的重排序既沒有改變單線程下程序運行的結果,又沒有對存在依賴關系的指令進行重排序。
產生的背景是為了確保多線程操作下具有內存可見性。
如果一個操作執行的結果需要對另一個操作可見,那么這兩個操作之間必須要存在happens-before關系。換句話說,操作1 happens-before 操作2,那么操作1的結果是對操作2可見的。
這里提到的兩個操作既可以是在一個線程之內,也可以是在不同線程之間。
規則:
程序順序規則:一個線程中的每個操作,happens-before 于該線程中的任意后續操作
監視器鎖規則:對一個鎖的解鎖,happens-before 于隨后對這個鎖的加鎖
volatile變量規則:對一個volatile域的寫,happens-before 于任意后續對這個volatile域的讀
傳遞性:如果A happens-before B,且B happens-before C,那么A happens-before C
start規則:如果線程A執行操作ThreadB.start()(啟動線程B),那么A線程的ThreadB.start()操作happens-before于線程B中的任意操作
join規則:如果線程A執行操作ThreadB.join()并成功返回,那么線程B中的任意操作happens-before于線程A從ThreadB.join()操作成功返回。
as-if-serial 語句保證單線程環境下不能改變程序執行的結果,happens-before 規則保證多線程環境下不能改變程序執行的結果。
關于如何深入理解Java多線程與并發框中重排序、屏障指令、as-if-serial規則就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。