首先看下下面这段代码:
public class Test{
private static boolean stop;
public static void main(String[] args){
new Thread(new Runnable(){
public void run(){
int i = 0;
while(!stop){
i++;
}
}
}).start();
TimeUnit.SECONDS.sleep(1);
stop = true;
}
}
我们期望主线程在1秒之后,将stop设置为true,使后台线程停止运行。
但是,在某些机器上,后台线程永远在循环!
问题在于:stop变量在主线程和后台线程中都被使用,但是没有设置同步,虚拟机在优化代码的时候,会将:
while(!stop){
i++;
}
转变为:
if(!stop){
while(true){
i++;
}
}
修正这个问题的一种方式是使用同步方式访问stop:
public class Test{
private static boolean stop;
private static synchronized void setStop(boolean s){
stop = s;
}
private static synchronized boolean getStop(){
return stop;
}
public static void main(String[] args){
new Thread(new Runnable(){
public void run(){
int i = 0;
while(!getStop()){
i++;
}
}
}).start();
TimeUnit.SECONDS.sleep(1);
setStop(true);
}
}
总结:在多个线程访问同一个数据,即使这个数据是原子的,为了保证一个线程写入的值对另一个线程可见,同步是非常必要的。