如果一个变量没有使用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方式运行得没问题,不代表直接运行也没问题。