关键在于 while(flag){}中不能有从主内存读取的操作:
常见的两种
- Thread.sleep,触发了线程的重新调度,保存当前线程上下文,即刷到主内存。
- 存在synchronized,当获取锁以后,清空本地内存中共享变量,从主内存进行加载,在释放锁时将本地内存中共享变量刷新到主内存中。
- System.out.println(); 中存在synchronized 同第二种;
/**
* volatile 保证可见性
* 验证这个问题的关键,不从主内存读,读取本地内存
*/
public class ThreadProblem {
public static class NoVolatile extends Thread {
//没有使用volatile
public boolean flag = Boolean.TRUE;;
@Override
public void run() {
System.out.println("flag is " + flag + " task start...");
while (flag) {
// 这常见的两种情况
// Thread.sleep(1000);
// synchronized (this){}
// System.out.println("running...");
}
System.out.println("flag is " + flag + " task end...");
}
public void setFlag(boolean flag) {
System.out.println("setting");
this.flag = flag;
}
}
public static class Volatile extends Thread {
//没有使用volatile
private volatile boolean flag = Boolean.TRUE;
@Override
public void run() {
System.out.println("flag is " + flag + " task start...");
while (flag) {}
System.out.println("flag is " + flag + " task end...");
}
public void setFlag(boolean flag) {
System.out.println("setting");
this.flag = flag;
}
}
}