当前位置: 首页 > 面试题库 >

有效不变的对象

芮化
2023-03-14
问题内容

我想确保根据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。有效的不可变对象

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


问题答案:

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

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



 类似资料:
  • 我想确保我正确理解根据Java内存模型的‘有效不可变对象’行为。 假设我们有一个可变类,我们希望将它发布为一个有效不可变的类: 我们执行以下操作: 问题是:Java内存模型是否保证所有线程必须具有? 根据Java并发实践,这应该是正确的,但如果我错了,请纠正我。 3.5.3.安全发布习语 要安全地发布对象,必须同时使对对象的引用和对象的状态对其他线程可见。通过以下方法可以安全地发布正确构造的对象:

  • 问题内容: 这是Java Concurrency in Practice中的一句话 共享的只读对象包括不可变的和实际上不可变的对象。 不变对象和有效不变对象之间有什么区别? 问题答案: 不可扩展且其字段全部为自身且不可变的类的实例是不可变的。 由于其方法的详细信息而无法更改其字段的类的实例实际上是不可变的。例如: 的某些实例实际上是不可变的,而有些则不是。 另一个例子是零长度数组。它们实际上是不可

  • 所以我读了关于HashMap的文章。有人曾指出: 我不太明白...为什么?

  • 第3.5.4节讨论了有效不可变的对象,即一旦一个对象被安全地完全构造,它的状态就不会被任何代码路径的任何代码所改变。 戈茨爵士举了一个例子: 总而言之,有效不可变对象的前提并不需要任何线程安全容器,因为我们不应该在任何代码路径中为有效不可变对象设置任何赋值代码。

  • 问题内容: 因此,我了解了HashMap。有人指出: “不可变性还允许缓存不同键的哈希码,这使整个检索过程非常快,并且表明String和Java Collection API提供的各种包装器类(例如)都是非常好的键。” 我不太明白…为什么? 问题答案: : 由于永不更改的内容,因此该类的创建者选择在对哈希进行一次计算之后就对其进行缓存。这样,不会浪费时间重新计算相同的值。

  • 问题内容: 我知道不可变对象始终具有相同的状态,即它们实际创建时的状态。它们的不变量由构造函数建立,并且由于它们的状态在构造后不会更改,因此这些不变量始终保持良好状态,这就是为什么可以在多线程环境中安全发布它们的原因。很好,但是由于我们生活在一个动态的世界中,程序的状态不断变化,如果通过不可变的对象构造程序的状态,那么这些对象会给我们带来什么好处? 问题答案: 您已经回答了“这些物品能给我们带来什