1. 程式人生 > >多執行緒變數同步機制

多執行緒變數同步機制

多執行緒中同一個變數會共享,但是有時候會發現不同執行緒中的共享變數,值不同步,原來每個執行緒都會有自己的記憶體存放變數的快取值,而不是一起使用主記憶體中的變數值。
問題:主執行緒的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;