線程安全之可見性問題

一.可見性問題

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內存模型中規定:

  1. 禁止緩存,對於volatile修飾的變量,不會走CPU高速緩存
  2. 對於和volatile修飾的變量所有相關的指令都不做指令重排
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章