多線程變量同步機制

多線程中同一個變量會共享,但是有時候會發現不同線程中的共享變量,值不同步,原來每個線程都會有自己的內存存放變量的緩存值,而不是一起使用主內存中的變量值。

問題:主線程的while循環中,當flag爲true時,循環體爲空的話,後面的打印語句不會執行,會一直在while裏循環;
而在循環體中加上一句語句,比如System.out.println(),循環就會正常結束,執行後面的輸出語句。
爲什麼當while循環體爲空時不會退出循環,加入一句打印就會退出循環?

例如:
 public class Test{
    public static void main(String args[]){
        R r=new R();
        Thread t=new Thread(r);
        t.start();
        while(!r.flag){
        }
        System.out.println("end");
    }
}

class R implements Runnable{
    public boolean flag=false;
    public void run(){
     int x=0;
        while(x<1000){
            x++;
            System.out.println(x);
        }
        flag=true;
    }

}

答:因爲多線程之間不是絕對同步的。 
在運行時爲了提高效率會將數據加載到寄存器中,所以有時雖然內存中數據已經改變,但還未即時更新到寄存器中,就會出現不同步的情況。
R線程的flag是從其工作內存取,主線程的while循環裏什麼都不寫,會導致調用訪問flag太頻繁,導致主內存不會及時刷新工作內存的flag,所以一直會訪問到flagfalse,當加入System.out.println()後,jvm的調度機制(會選擇在執行其他任務的時候同步flag)(訪問flag有了明顯間隔),所以當加了一句打印語句之後,主內存就有空去刷新到R線程的工作內存,發現flag更新了,這樣才能正常退出while循環。

volatile 關鍵字可以強制每次都從主內存中讀取,而不是用自己線程工作內存中的緩存,這樣可以實現同步變量,但效率會低不少。
例如:
volatile boolean flag=false;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章