volatile 关键字验证问题

新手上路,请多包涵

使用网上流传的验证 volatile 内存可见性的代码验证的时候,发现一个问题,具体出现在代码的【1】处。
问题:
不加输出语句,则可以验证主线程读取不到 "another thread" 修改的 age 值;
加了输出语句后,就会跳出循环。
猜测:

  1. sychronized 有关?是 synchronized 强制刷新了工作内存的变量值吗?
  2. "another thread" 修改完 age 变量的值是什么时候刷新到主内存的呢?

希望有大佬可以帮忙解答一下。

class PersonVolatile {
    Integer age = 0;

    public void changeAge(){
        this.age = 1;
    }
}
public class TestVolatile {
    @SneakyThrows
    public static void main(String[] args) {
        PersonVolatile personVolatile = new PersonVolatile();
        new Thread(()->{
            System.out.println(Thread.currentThread().getName() + " execute");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            personVolatile.changeAge();
            System.out.println(Thread.currentThread().getName() + " has changed age, now age = " + personVolatile.age);
        }, "another thread").start();

        while (personVolatile.age == 0){
            System.out.println(personVolatile.age); // [1] 有问题
        }
        
        System.out.println(Thread.currentThread().getName() + " age = " + personVolatile.age);
    }
}
阅读 1.2k
1 个回答

System.out.println() 方法内部实现包含了 synchronized 同步代码块,synchronized 是可以保证线程同步以及内存的可见性的。

可以试试换成 synchronized (personVolatile) {},结果一样。

package com.xxg.xtoolkit.decorator;

class PersonVolatile {
    Integer age = 0;

    public void changeAge(){
        this.age = 1;
    }
}
public class TestVolatile {
    public static void main(String[] args) {
        PersonVolatile personVolatile = new PersonVolatile();
        new Thread(()->{
            System.out.println(Thread.currentThread().getName() + " execute");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            personVolatile.changeAge();
            System.out.println(Thread.currentThread().getName() + " has changed age, now age = " + personVolatile.age);
        }, "another thread").start();

        while (personVolatile.age == 0){
            synchronized (personVolatile) {}
        }

        System.out.println(Thread.currentThread().getName() + " age = " + personVolatile.age);
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进