【问题标题】:in java how to replace an immutable object在java中如何替换不可变对象
【发布时间】:2013-01-29 06:31:29
【问题描述】:

如何

假设我有这门课

@ImmutableWannabe
public class ConfigurationHolder {
  @ImmutableButHowToMakeSureNoTwoThreadsOverrideOneEachOtherWhenReplacingReference
  private Map<System, Configuration> mySysConfig  = ImmutableMap.builder<>getSomeConfigurations....build();
  ConfigurationHolder(copy constructor) {
     mySysConfig = ImmutableMap.builder().of(inputSysConfig);
  }
}

现在假设其中一个系统配置已更新,我需要更新此映射,但我需要以线程安全的方式进行。这意味着如果两个线程尝试更新相同系统数据的相同配置,它们应该是一致的,并且它们不应该相互覆盖。

不变性对我有什么帮助?据我所见,如果是的话,我仍然需要锁定如何正确执行?

所以我的一般问题是:任何可以随系统时间更改的 immutableObject 是否会导致我们需要锁定需要更改其 ImmutableObjectHolder 的代码?没看懂……

有人可以给出一个正确的例子吗?

谢谢

【问题讨论】:

  • 您无法更新不可变地图,但您可以将持有者指向其他地图。这样,任何线程都不会看到不一致的地图(它们只会看到旧地图或新地图,但不会出现奇怪的混合)。
  • 是的,但是当我将它指向另一个地图时,我不需要确保两个线程知道两个不同的地图,因为他们在两个不同的时间点读取它们现在正在改变指向两个不同的指针,这会导致错误吗?如果是这种情况,我仍然需要担心 immutableObjects 的锁,对吗?
  • 如果您有两个线程想要更​​新持有者,那么是的,它们需要锁定(乐观或悲观)。你可能想要一个 AtomicReference 。但是只读取的线程不需要任何锁定。
  • 如果你要更新ImmutableMap,你真的不应该将ConfigurationHolder标记为不可变。
  • 是的,所以在行的末尾总会有一个可变对象来保存所有这些不可变对象,对吧? (如果我需要替换不可变的,这里有什么逃避以避免任何类型的可变持有者吗?)。

标签: java multithreading concurrency immutability


【解决方案1】:

假设你的地图是一些实例变量,最简单的方法是让它volatile。或者,为它创建一个 getter 和 setter,并将它们设为 synchronized。即,使用标准技术。请注意,如果客户端试图聪明并将值缓存在局部变量中,这将无济于事。 (我已经被这个 bug 咬过几次了。)

我想作为替代方案,您可以设置一些 MyImmutableChanged 事件/侦听器。

而且,你是对的,不变性并不能解决所有线程问题。

【讨论】:

  • 非常感谢,您能否详细说明一下在这种情况下我何时使用 volatile 以及在这种情况下何时使用 AtomicReference?
  • 请参阅 [此 SO 帖子] (stackoverflow.com/questions/281132/…)。简短的回答是两者都有效。我倾向于使用 volatile,因为我从没想过 AtomicReference。 :-)
猜你喜欢
  • 2014-08-24
  • 1970-01-01
  • 2021-05-04
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
  • 2014-09-03
  • 1970-01-01
相关资源
最近更新 更多