Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

令人迷惑的volatile例子(一) #8

Open
seaswalker opened this issue Jun 27, 2020 · 0 comments
Open

令人迷惑的volatile例子(一) #8

seaswalker opened this issue Jun 27, 2020 · 0 comments

Comments

@seaswalker
Copy link
Owner

seaswalker commented Jun 27, 2020

通常情况下关于volatile用法的正确例子是这样:

private volatile boolean flag = true;

@org.junit.Test
public void testVolatile() {
    new Thread(() -> {
        try {
            System.out.println("子线程启动");
            TimeUnit.SECONDS.sleep(3);
            flag = false;
            System.out.println("flag false");
        } catch (InterruptedException ignore) {
        }
    }).start();

    while (flag) {
    }
}

结果也确实如此,不会导致死循环,与之相反如果把volatile去掉:

private boolean flag = true;

的确会死循环,于是我们得出结论:必须使用volatile保证内存可见性。然而事实并不是如此,下面的例子只在while (flag)中加入一句无关痛痒的代码:

private boolean flag = true;

@org.junit.Test
public void testVolatile() {
    new Thread(() -> {
        try {
            System.out.println("子线程启动");
            TimeUnit.SECONDS.sleep(3);
            flag = false;
            System.out.println("flag false");
        } catch (InterruptedException ignore) {
        }
    }).start();

    while (flag) {
        System.out.print(1);
    }
}

你会发现,现在也不会死循环了。
其实,在X86平台上,即使不使用memory barrier处理器也会保证变量修改的全局可见。参考:
Does a memory barrier ensure that the cache coherence has been completed?

上面那个例子死循环的原因其实是JVM编译器优化,将代码实际上变成了(加上volatile或打印阻止了这种优化):

if (flag) {
    while (true) {}
}

参考:请问R大 有没有什么工具可以查看正在运行的类的c/汇编代码

那X86既然已经保证了全局可见,为什么我们还要使用volatile?Java毕竟是跨平台的语言,也许就会运行在不保证全局可见的处理器上,那时就会出错了。
所以如果你没在这种场景下用volatile,并不是你写的对,而是你恰好把代码跑在了X86上而已。

@seaswalker seaswalker changed the title 令人迷惑的volatile例子 令人迷惑的volatile例子(一) Jul 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant