java - volatile 保证可变对象的安全发布?

标签 java multithreading concurrency volatile safe-publication

通过阅读 Java 并发实践

我能看到:

要安全地发布对象,对象的引用和对象的状态必须同时对其他线程可见。正确构造的对象可以通过以下方式安全发布:

  • 从静态初始化程序初始化对象引用
  • 将对它的引用存储到 volatile 字段或 AtomicReference
  • 将对它的引用存储到正确构造的对象的最终字段中
  • 将对它的引用存储到一个由 锁。

但是,我对第二个成语感到困惑。由于 volatile 只能保证引用对另一个线程可见,但它不同步它引用的对象构造。那么它如何保证可变对象被正确构造,正在构造这个对象的线程被另一个线程中断了?

最佳答案

我们需要证明构造一个对象并将其分配给一个 volatile 变量发生在从该变量读取之前。

From JLS Chapter 17:

If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

因此,对象的构造发生在它被分配给一个 volatile 变量之前,从该线程的角度来看。

If an action x synchronizes-with a following action y, then we also have hb(x, y).

和:

If hb(x, y) and hb(y, z), then hb(x, z).

如果我们能证明写入 volatile 变量( Action y)读取变量( Action z)同步,我们就可以使用happens-before 的传递性表明构造对象( Action x)happens-before 读取对象。幸运的是:

A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).

因此,我们可以看到,以这种方式发布时,正确构造的对象对任何线程都是可见的。

关于java - volatile 保证可变对象的安全发布?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40118804/

相关文章:

c# - 从另一个线程使用 Unity API 或在主线程中调用函数

Java 和 2 个线程

c++ - 多线程引擎窗口随机减速

c - 无锁队列中的内存屏障使用

java - 将 MainActivity.java 移动到子文件夹中后执行失败

Java - 在 Java 程序中运行带有 args 的 java 程序

java - 如何在 Java 中测试不同的 "tables input"?

java - 将 blob(文本文件)从 Azure 存储以 UTF8 下载到内存?

Java Swing 线程问题

swift - 在 Swift 中,当两个线程获取并设置一个非线程安全属性时会发生什么?