一.可見性問題
1.CPU指令重排
Java編程語言爲了增強效率,其的語義允許Java編譯器和微處理器進行執行優化,
這些優化導致了與其交互的代碼不再同步,從而導致出現看似矛盾的行爲。
比如代碼
boolean isTrue = true;
while (isTrue){
//...
}
在循環判斷執行一定次數,變量isTrue的值一直爲true,則CPU就會將該代碼進行指令重排
boolean isTrue = true;
if (isTrue) {
//...
}
變成if(true),這樣在變量isTrue的值被更改後,還是不會出現
又比如代碼如果在多線程的情況下
//線程A
int a = 10;
a = 20;
boolean flag = true;
線程B中的代碼
//線程B
while(flag){
System.out.println(a);
}
如果指令重排將flag賦值true指令重排在 a = 20之前的話,輸出的結果就會不一樣了
2.CPU高速緩存
線程與主內存進行交互,中間還有層CPU高速緩存,而這段進出高速緩存期間也有極小的可能出現數據不一致的問題
二.volatile關鍵字
何爲可見性?
讓一個線程對共享變量的修改,能夠及時的被其他線程看到 。
volatile爲何能實現線程間的可見?
java內存模型中規定:
- 禁止緩存,對於volatile修飾的變量,不會走CPU高速緩存
- 對於和volatile修飾的變量所有相關的指令都不做指令重排