多线程中同一个变量会共享,但是有时候会发现不同线程中的共享变量,值不同步,原来每个线程都会有自己的内存存放变量的缓存值,而不是一起使用主内存中的变量值。
问题:主线程的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;