1. 程式人生 > >java 多執行緒下的原子操作了解認識

java 多執行緒下的原子操作了解認識

public class Test {
    
    boolean flag= false;

    public void changeFlag(){
        flag = true;
    }

    public void execute(){
        if(flag){
            System.out.println("execute....");
        }
    }
}

首先看上述程式碼:很簡單,但是在這裡如果有:執行緒A執行changeFlag方法之後,執行緒B再執行execute方法,試問,execute方法會不會打印出:execute....呢?  (是的,這個是多執行緒的案例,由他來引入;)

答案是:不一定會;

原因:

一般情況下,會執行列印的方法,就說說不會列印的理由,

執行緒A在執行完flag = true;之後,還未完全退出執行緒A,這時執行緒B搶到CUP資源,開始執行execute方法,判斷flag的值時,flag的值依然為false;

因為在java記憶體模型中,多執行緒之間的變數值是不可見的;每個執行緒都有自己獨立的working memory(工作記憶體),裡面儲存該執行緒使用到的變數的副本;程式在執行之前,所有變數都存在主記憶體當中,執行緒記憶體會往主記憶體中拷貝一份變數的副本,執行緒執行結束後,會將副本變數值賦給主記憶體中對應的變數,然後主記憶體再將修改後的變數賦值到每個執行緒的副本中;所以執行緒之間變數值的傳遞需要通過主記憶體完成;而執行緒之間的變數(全域性)是不能互相訪問的;

回到當前例項,所以這就是執行緒A中的flag為false的原因;

在這裡涉及到java記憶體模型知識;針對上述例子大致說說原因,推薦連結:https://www.cnblogs.com/rocomp/p/4780532.html

通過上述例子餘留了一個問題:如何才能使得執行緒之間的變數(全域性)可見?

java語言支援可見性的實現方法:

synchronize、volatile、final

這裡主要說說volatile:

如果在上述例子中flag宣告前加上volatile;那麼答案就是肯定的了;

但是volatile就可以萬能了?當然不是:如下例子:

public class Test{

    public volatile int i=0;

    public void test1(){
        for(i;i<1000;i++){
            system.out.println(i);
        }
    }
}

上述程式碼,在多執行緒執行該方法的情況下,是否會列印到1000呢,如果不會可以加到10000或更大,然後讓執行緒睡三秒,執行結果卻不是我們想要的(1.到1000依次列印);

列印結果坑定少於1000,那麼為什麼會出現此問題呢?

這裡就是原子操作的原因:For Example 例如:

以下多執行緒對int型變數x的操作,哪幾個需要進行同步:( )
A. x=y; B. x++; C. ++x; D. x=1;

博文轉載:https://blog.csdn.net/encoder1234/article/details/52228224

看了上面的連結博文後,是否明白原因了呢?  是的,上述答案除了D外,全是;

volatile雖然線上程之間變數有可見性,但是卻並沒有保證原子操作;

假如x是一個long或者double型別,且當前系統是32位的,那麼,D選項也需要同步;

java對long和double的賦值操作是非原子操作!!long和double佔用的位元組數都是8,也就是64bits。在32位作業系統上對64位的資料的讀寫要分兩步完成,每一步取32位資料。這樣對double和long的賦值操作就會有問題:如果有兩個執行緒同時寫一個變數記憶體,一個程序寫低32位,而另一個寫高32位,這樣將導致獲取的64位資料是失效的資料。因此需要使用volatile關鍵字來防止此類現象。volatile本身不保證獲取和設定操作的原子性,僅僅保持修改的可見性。但是java的記憶體模型保證宣告為volatile的long和double變數的get和set操作是原子的。

那麼怎樣才能讓全域性變數既方便又安全呢?

請關注:CAS

推薦CAS博文:

https://www.jianshu.com/p/efb2024808a0

http://www.blogjava.net/xylz/archive/2010/07/04/325206.html

推薦volatile博文:

https://www.cnblogs.com/chengxiao/p/6528109.html

https://www.cnblogs.com/zhengbin/p/5654805.html