java - 从未分配为 null 的 volatile 变量是否可以包含 null?

标签 java multithreading volatile

可以在以下概念性 Java 示例中:

public class X implements Runnable {
    public volatile Object x = new Object();

    @Runnable
    public void run() {
        for (;;) {
            Thread.sleep(1000);
            x = new Object();
        }
    }
}

x 曾被另一个线程读取为 null 吗?

奖励:我是否需要将其声明为 volatile(我并不真正关心该值,它足以在将来的某个时候成为新分配的值并且永远不会为 null)

最佳答案

从技术上讲,是的。这是原始ConcurrentHashMap's readUnderLock的主要原因. javadoc 甚至解释了如何:

Reads value field of an entry under lock. Called if value field ever appears to be null. This is possible only if a compiler happens to reorder a HashEntry initialization with its table assignment, which is legal under memory model but is not known to ever occur.

由于 HashEntry 的 value 是易变的,这种类型的重新排序在构造上是合法的。

这个故事的寓意是所有非最终初始化都可以与对象构造竞争。


编辑: @Nathan Hughes 问了一个有效的问题:

@John: in the OP's example wouldn't the construction have happened before the thread the runnable is passed into started? it would seem like that would impose a happens-before barrier subsequent to the field's initialization.

Doug Lea 对这个话题有几条评论,整个话题可以是 read here .他回答了评论:

But the issue is whether assignment of the new C instance to some other memory must occur after the volatile stores.

有了答案

Sorry for mis-remembering why I had treated this issue as basically settled: Unless a JVM always pre-zeros memory (which usually not a good option), then even if not explicitly initialized, volatile fields must be zeroed in the constructor body, with a release fence before publication. And so even though there are cases in which the JMM does not strictly require mechanics preventing publication reordering in constructors of classes with volatile fields, the only good implementation choices for JVMs are either to use non-volatile writes with a trailing release fence, or to perform each volatile write with full fencing. Either way, there is no reordering with publication. Unfortunately, programmers cannot rely on a spec to guarantee it, at least until the JMM is revised.

并完成了:

  • Programmers do not expect that even though final fields are specifically publication-safe, volatile fields are not always so.

  • For various implementation reasons, JVMs arrange that volatile fields are publication safe anyway, at least in cases we know about.

  • Actually updating the JMM/JLS to mandate this is not easy (no small tweak that I know applies). But now is a good time to be considering a full revision for JDK9.

  • In the mean time, it would make sense to further test and validate JVMs as meeting this likely future spec.

关于java - 从未分配为 null 的 volatile 变量是否可以包含 null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34341547/

相关文章:

java - 提出 SOAP 请求时出现问题

java - 如何通过单击或单个命令运行 Selenium 测试?

c++ - 具有两个线程的 STL 队列(生产者、消费者)

c# - 如何确保特定的后台工作线程在另一个后台工作线程之前执行?

java - 不理解 'volatile' 关键字

java - Gradle 任务取决于单独项目中的任务

c++ - pthread 多线程

java - 多线程中读取字段

java - Android Studio 2.0 更新 - public static volatile com.android.tools.fd.runtime.IncrementalChange

java - 如何按位置设置 ListView 中特定项目的背景颜色?