1. 程式人生 > >Java之多執行緒記憶體可見性_2(synchronized可見性原理)

Java之多執行緒記憶體可見性_2(synchronized可見性原理)

可見性:
要實現共享變數的可見性,必須保證2點:
1.執行緒修改後的共享變數值能夠及時從工作記憶體重新整理到主記憶體中。

2.其他執行緒能夠及時把共享變數的最新值從主記憶體更新到自己的工作記憶體中。

以下的記錄都是來源於慕課網-細說java多執行緒之記憶體可見性

Java語言層面你支援的可見性實現方式:(不包含jdk1.5之後的一些高階特性)
1.synchronized
2.volatile

synchronized 實現可見性
synchronized能夠實現:
1.原子性(同步)
2.可見性

JMM關於synchronized的兩條規定:
1.執行緒解鎖前,必須把共享變數的最新值重新整理到主記憶體中
2.執行緒加鎖時,將清空工作記憶體中共享變數的值,從而使用共享變數時需要從主記憶體中
 重新讀取最新的值(注意:加鎖與解鎖需要時同一把鎖)
 
注:執行緒解鎖前對共享變數的修改能在下次加鎖時對其他執行緒可見


synchronized實現可見性
執行緒執行互斥程式碼的過程:

1.獲得互斥鎖
2.清空工作記憶體
3.從主記憶體拷貝變數的最新副本到工作記憶體
4.執行程式碼
5.將更改後的共享變數的值重新整理到主記憶體
6.釋放互斥鎖

重排序
重排序:程式碼書寫的順序與實際執行的順序不同,指令重排序是編譯器或處理器為了提高程式效能
而做的優化


1.編譯器優化的重排序(編譯器優化)
2.指令級並行重排序(處理器優化)
3.記憶體系統的重排序(處理器優化)

如:可能會出現下面的結果
程式碼順序:                             執行順序
int number = 1;                   int result = 0;
int result = 0;                   int number = 1;

as-if -serial
as-if-serial:無論如何重排序,程式執行的結果應該與程式碼順序執行的結果一致(Java編譯器、
執行時和處理器都會保證java在單執行緒下遵循as-if-serial語義)

如:
    int num1 = 1;
int num2 = 2;
int sum = num1+num2;
單執行緒:第1、2行的循序可以重拍,但第三行不能
重排序不會給單執行緒帶來記憶體可見性問題
多執行緒中程式交錯執行時,重排序可能會造成記憶體可見性問題