【问题标题】:Java volatile on primitivs [duplicate]Java volatile on primitivs [重复]
【发布时间】:2013-03-25 01:49:25
【问题描述】:

为什么我们需要在原语上使用 volatile?我发现的最常见的例子是that

volatile boolean shutdownRequested;

...

public void shutdown() { shutdownRequested = true; }

public void doWork() { 
    while (!shutdownRequested) { 
        // do stuff
    }
}

但是当我试图自己运行它时。 易失性声明没有任何改变。它以易失性和非易失性停止shutdownRequested

【问题讨论】:

标签: java volatile primitive


【解决方案1】:

本质上,volatile是用来表示一个变量的值会被不同的线程修改。

一个 volatile Java 变量意味着:

这个变量的值永远不会被缓存在线程本地:所有的读写都将直接进入“主内存”; 并且对变量的访问就像它被包含在一个同步块中一样,在其自身上同步。

【讨论】:

    【解决方案2】:

    未标记为volatile 的变量可以根据JVM 的意愿缓存。例如,可以将变量的副本加载到寄存器中,然后可能从不引用原始实例变量,尤其是在紧密循环中。

    将其标记为 volatile 告诉 JVM 它必须始终引用原始实例变量。

    你看到的可能只是 JVM 没有缓存变量,即使它被允许。

    这也是多线程代码难以证明正确的原因之一。不仅不是所有的 JVM 都以相同的方式工作,而且与运行代码相比,在调试代码时甚至可能会得到不同的结果,如果它在多核单元上运行,它可能再次以不同的方式运行..

    【讨论】:

      【解决方案3】:

      volatile 对于多线程代码很有用。

      看到这个问题:Do you ever use the volatile keyword in Java?

      【讨论】:

        【解决方案4】:

        对 volatile 变量的更改始终对其他线程可见。 enter link description here

        在您的示例中,一个线程正在执行 doWork() 并且另一个线程出现并调用关闭。在某些平台上的某些 JVM 上,编译器可能会以这样一种方式优化事物,即工作线程看不到对 shutdownRequested 变量的更改,例如变量可以缓存在寄存器中。

        【讨论】:

          【解决方案5】:

          当您想确保读取的值是当前值,没有任何缓存时,您应该使用volatile 变量。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-06-03
            • 2011-04-05
            • 2014-06-26
            • 2012-12-29
            • 2015-12-28
            • 2017-08-29
            • 2021-09-05
            相关资源
            最近更新 更多