添加volatile后为什么 存在 a=1;b=3 却不存在b=3;a=1呢?怎么解释?

来源:12-10 可见性问题

_殷歪歪

2019-10-27


/**
 * 存在   a=1;b=3
 * 不存在 b=3;a=1
 */
public class Test {
    volatile int a = 1;
    volatile int b = 2;

    private void write() {
        a = 3;
        b = a;
    }

    private void read() {
        System.out.println("a=" + a + ";b=" + b);
        System.out.println("b=" + b + ";a=" + a);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 200000; i++) {
            Test test = new Test();
            new Thread(() -> {
                try {
                    Thread.sleep(1);
                    test.write();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();

            new Thread(() -> {
                try {
                    Thread.sleep(1);
                    test.read();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}


写回答

1回答

悟空

2019-10-27

小伙伴的提问很好,这是由于非原子性导致的。

你代码里的打印是先打印a,然后打印b,而课程里的是先打印b然后打印a,由于println的非原子性性质,所以打印顺序是有区别的。课程里的代码,是不会出现b=3;a=1的情况的。

因为System.out.println(“a=” + a + " b=" + b)这一句不是原子的,所以执行期间是可以被切换的:先读取a的值为1并打印后,线程被切换走执行change(),此时b的值刚刚发生了变化(打印a的时候,b的值其实是2,但是现在变成了3),于是就会出现a=1,b=3。但是如果先打印b再打印a,那么打印了b之后,由于volatile的保证,可以确定a=3已经执行了并且最新值可以被所有线程看到,所以就不会出现b=3;a=1的情况,你可以试一下。

小伙伴还可以看下:https://coding.imooc.com/learn/questiondetail/141325.html

5
0

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

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

2512 学习 · 939 问题

查看课程