请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

volatile不能保证原子性

本小节视频里老师给变量a,b加上了volatile关键字解决可见性问题。
然后说不可能出现a=1 b=3的情况。但是我在本机上测试了以下代码,发现是可以出现a=1 b=3的情况的。
我的分析是print()方法中System.out.println(“a=” + a + " b=" + b);这一句不是原子的,所以可能执行一半就发生了线程切换。比如:
线程1执行print()方法,此时a=1,b=2,
System.out.println(“a=” + a + " b=" + b)运行到一半,切换到线程2,线程2执行change()方法,此时a=3,b=3。
然后切换回线程1,继续执行未执行完的System.out.println(“a=” + a + " b=" + b),那么得到的结果就是a=1 b=3。
不知道我这么分析的对不对,希望老师能帮看看,谢谢!

package jmm;

public class FieldVisibility {

    volatile int a = 1;
    volatile int b = 2;

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

    private void print() {
	    // 这一句不是原子的,所以由于线程切换依然可能得到a=1 b=3
        System.out.println("a=" + a + " b=" + b);
    }

    public static void main(String[] args) {
        while (true) {
            FieldVisibility test = new FieldVisibility();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    test.change();
                }
            }).start();

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    test.print();
                }
            }).start();
        }
    }
}

图片描述

正在回答

2回答

悟空 2019-09-08 23:38:20

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

你代码里的打印是先打印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的情况,你可以试一下。

11 回复 有任何疑惑可以回复我~
  • 提问者 慕勒4339842 #1
    非常感谢!
    回复 有任何疑惑可以回复我~ 2019-09-09 02:26:48
yao314 2019-09-30 11:18:30

非常感谢这位同学的提问猜想和老师的解答方案。

5 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信