【執行緒知識點】--可見性
阿新 • • 發佈:2019-01-29
可見性
- 可見性:一個執行緒對共享變數的修改,能夠及時的被其它執行緒看到。
- 共享變數:如果一個變數在多個執行緒的工作記憶體中都存在副本,那麼這個變數就是這幾個執行緒的共享變數。
Java記憶體模型
- 所有的變數都存貯在主記憶體中
- 每個執行緒都擁有自己獨立的工作記憶體,裡邊儲存該執行緒使用到的變數副本(主記憶體中該變數的一份拷貝)
兩條規定:
- 執行緒對共享變數的所有操作都必須在自己的工作記憶體中進行,不可以直接操作主記憶體
- 不同執行緒之間無法直接訪問對方工作記憶體中的共享變數,執行緒之間共享變數的傳遞需要通過主記憶體來完成。
共享變數可見性實現的原理
執行緒1對貢獻變數的修改想要及時被執行緒2看到,那麼必須進行如下兩個步驟:
- 把執行緒1的工作記憶體中共享變數的值重新整理到主記憶體中。
- 把主記憶體中共享變數的最新值更新到執行緒2的工作記憶體中。
記憶體可見性的實現
synchronized實現可見性
synchronized能夠實現:
- 原子性(同步,互斥鎖)
- 可見性
JMM對synchronized的兩條規定:
- 執行緒解鎖前,必須把共享變數的最新值重新整理到主記憶體中
- 執行緒解鎖時,會將工作記憶體中的值標註為失效,重新加鎖時如果發現值失效,那麼就從主記憶體中重新讀取一次。(注意:這裡指的是同一把鎖)
以上兩點實現的效果:
執行緒解鎖前對共享變數的修改,在下次加鎖的時候對其他執行緒可見。
重排序
重排序:程式碼書寫的順序和實際執行的順序不同,指令重排序是編譯器或者是處理器為了提高程式的效能而做的優化。
具體有以下三種:
- 編譯器優化的重排序(編譯器優化)
- 指令級並行重排序(處理器優化)
- 記憶體系統的重排序(處理器優化)
as-if-serial:無論如何重排序,程式執行的結果都應該和程式碼順序執行的結果一致(java編譯器和處理器都會保證java在單執行緒下遵循as-if-serial語義)
int num1 = 1;
int num2 = 2;
int sum = num1 + num2;
單執行緒:第一行和第二行的順序可以重排,但是第三行不能。
- 重排序不會給單執行緒帶來記憶體可見性的問題
- 多執行緒中程式交錯執行的時候,重排序就可能會帶來記憶體可見性問題了
歡迎關注公眾號~