多線程中同一個變量會共享,但是有時候會發現不同線程中的共享變量,值不同步,原來每個線程都會有自己的內存存放變量的緩存值,而不是一起使用主內存中的變量值。
問題:主線程的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
值,所以一直會訪問到flag
爲false
,當加入System.out.println()
後,jvm的調度機制(會選擇在執行其他任務的時候同步flag)(訪問flag
有了明顯間隔),所以當加了一句打印語句之後,主內存就有空去刷新到R
線程的工作內存,發現flag更新了,這樣才能正常退出while
循環。
volatile 關鍵字可以強制每次都從主內存中讀取,而不是用自己線程工作內存中的緩存,這樣可以實現同步變量,但效率會低不少。
例如:
volatile boolean flag=false;