贴代码:
class sss extends Thread { //设置类静态变量,各线程访问这同一共享变量 private static boolean flag = false; //无限循环,等待flag变为true时才跳出循环 public void run() { while (!flag) { //如果把这句打印语句解除注释,那么就会退出循环;或者解除下面的同步语句块 //System.out.println("ss"); // 1 /*synchronized (""){ // 2 }*/ } System.out.println(flag); } public static void main(String[] args) throws Exception { new sss().start(); Thread.sleep(100); flag = true; System.out.println("over"); } }
以上代码执行会进入死循环,因为main线程和sss线程各自有一个工作内存,main方法里面虽然改了flag=true,但是sss线程里面是不能看到的,还是用其本地内存取flag的值,所以导致死循环;
可以看到run还是红的,正在运行
解决的办法①:
private volatile static boolean flag = false;
给flag加上volatile修饰,存在两个直观作用:
1、使main线程改变flag值后立即刷新到主内存
2、使其他线程缓存的flag值无效,从主内存再次读取flag的值。
那么main线程把flag改为true后,sss线程是可以立即得到最新的值,所以退出循环
解决方法②:
在while循环里面加上打印语句
while (!flag) { //如果把这句打印语句解除注释,那么就会退出循环;或者解除下面的同步语句块 System.out.println("ss"); // 1 /*synchronized (""){ // 2 }*/ }
原因:
public void println(String x) { synchronized (this) { print(x); newLine(); } }
println方法里面是加了同步锁的,那么就会清空工作内存,再次从主内存读取值,所以同样可以读取最新的flag值
同理,直接在里面使用
synchronized 块
所以看到有些博客说
System.out.println("ss");
这条语句起了同步内存的作用是误导。