一尘不染

有效不变的对象

java

我想确保根据Java内存模型正确理解“有效不可变对象”的行为。

假设我们有一个可变的类,我们希望将其发布为有效的不可变的类:

class Outworld {
  // This MAY be accessed by multiple threads
  public static volatile MutableLong published;
}

// This class is mutable
class MutableLong {
  private long value;

  public MutableLong(long value) {
    this.value = value;
  }

  public void increment() {
    value++;
  }

  public long get() {
    return value;
  }
}

我们执行以下操作:

// Create a mutable object and modify it
MutableLong val = new MutableLong(1);
val.increment();
val.increment();
// No more modifications
// UPDATED: Let's say for this example we are completely sure
//          that no one will ever call increment() since now

// Publish it safely and consider Effectively Immutable
Outworld.published = val;

问题是 :Java内存模型是否保证所有线程都必须具有Outworld.published.get() == 3

根据 Java Concurrency In Practice, 这应该是正确的,但是如果我错了,请更正我。

3.5.3。安全出版惯用语

为了安全地发布对象,必须同时使对该对象的引用和该对象的状态对其他线程可见。可以通过以下方式安全地发布正确构造的对象:
-从静态初始化程序初始化对象引用;
-将对它的引用存储到volatile字段或AtomicReference中;
-将对它的引用存储到正确构造的对象的最终字段中;或
-将对其的引用存储到由锁适当保护的字段中。

3.5.4。有效的不可变对象

安全发布的有效不变对象可以被任何线程安全使用,而无需额外的同步。


阅读 220

收藏
2020-12-03

共1个答案

一尘不染

是。在读取之前,对的写入操作MutableLong后跟一个happens-before关系(在volatile上)。

(有可能一个线程Outworld.published不安全地读取并将其传递给另一个线程。从理论上讲,它可以看到更早的状态。实际上,我看不到它的发生。)

2020-12-03