如果一个变量没有使用volatile标识,则可能存在跨线程可见性问题; 但经验发现,断点调试时,这个可见性问题可能会消失。
比如,
package player.kent.chen.learn.hivolatile;
/**
* 循环直到有人喊停
*/
public class LoopUntilCommandForBoolBean {
private BoolBean bean = new BoolBean(false);
/**
* 循环直到有人喊停
*/
public void loop() {
System.out.println("loop starts");
while (!bean.isStop()) {
;
}
System.out.println("Stopped because somebody said so");
}
/**
* 喊停
*/
public void sayStop() {
bean.setStop(true);
System.out.println("Stop said");
}
public static void main(String[] args) throws InterruptedException {
final LoopUntilCommandForBoolBean luc = new LoopUntilCommandForBoolBean();
Thread t = new Thread(new Runnable() {
public void run() {
luc.loop();
}
});
t.start(); //启动循环线程
Thread.sleep(1000);
luc.sayStop(); //喊停
}
private static final class BoolBean {
private boolean stop;
/**
* @param stop
*/
public BoolBean(boolean stop) {
super();
this.stop = stop;
}
public boolean isStop() {
return stop;
}
public void setStop(boolean stop) {
this.stop = stop;
}
}
}
直接运行时,这个程序会陷入死循环; 但你如果在isStop()处设个断点,以debug的方式来运行程序,很有可能会使stop变量变得可见。
具体为什么会这样,我找了很久没找到答案; 但这个现象可以提醒我们:
对于牵涉到JMM的问题,用debug方式运行得没问题,不代表直接运行也没问题。