为什么没加volatile,公共变量的更改对子线程还是可见的

来源:10-5 找到错误2

weixin_慕尼黑2067412

2019-10-25

import java.util.concurrent.TimeUnit;

public class test1 {
    private static  boolean ready;
    private  static  int num;
    private static  class  NoVisiu implements  Runnable{
        @Override
        public void run() {
            while(!ready){
                System.out.println(num);
            }
            System.out.println(num);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(new NoVisiu());
        t.start();
        TimeUnit.SECONDS.sleep(1);
        num=42;
        ready=true;
        TimeUnit.SECONDS.sleep(1);
    }
}

启动server模式后,按道理说会一直执行 。但是最终会输出42结束。
server模式是怎么启动的?
图片描述

写回答

2回答

悟空

2019-10-25

我知道你这个截图的来源,我认为这个截图的说法是有问题的。

即便是server模式,也并不是就不可见,相反,JVM还是会努力保证可见性,进行主内存和工作内存的同步。

0
3
weixin_慕尼黑2067412
非常感谢!
2019-10-25
共3条回复

Mydog

2020-01-15

这个好像和我提的System.out.println方法问题类似,System.out.println里面有synchronized代码块修饰,由于ready被设置为true之前,有sleep操作,在sleep执行完后,主线程中ready变为了true,子线程里执行的println方法包含了执行synchronized代码块时,JVM提升了ready变量的可见性,此时while循环终止;


可以把run里面的System.out.println注释掉,或换为num++,这时候就一直无法终止了;


不知道我理解的对不对

0
1
Mydog
还可以试下,run方法里面,不用System.out.println(),直接使用 synchronized (this){ //注意是this锁 // num++; } 遇到synchronized修饰的代码块,也是一样会终止。
2020-01-15
共1条回复

线程八大核心+Java并发原理及企业级并发解决方案

完整的并发知识网络+丰富的工作内容分享+50余道并发高频面试题

2512 学习 · 939 问题

查看课程