EnumMap与并发put / get

时间:2014-01-21 11:41:28

标签: java concurrentmodification enum-map

我正在考虑在并发环境中使用EnumMap。然而,环境是非典型的,这就是原因:

  • EnumMap始终已满:当地图暴露于并发环境时,没有未映射的密钥
  • 只会使用put()和get()操作(没有迭代,没有remove()等)
  • 如果get()不立即/有序地反映put(),则完全可以接受

从我可以收集的内容,包括相关的方法源代码,这似乎是一个安全的场景(不同于允许迭代)。有什么我可能忽略的吗?

3 个答案:

答案 0 :(得分:3)

直接来自JavaDoc

  

与大多数集合实现一样,EnumMap未同步。如果多个线程同时访问枚举映射,并且至少有一个线程修改了映射,则应该在外部进行同步。这通常通过在自然封装枚举映射的某个对象上同步来完成。如果不存在此类对象,则应使用Collections.synchronizedMap(java.util.Map<K, V>)方法“包装”地图。这最好在创建时完成,以防止意外的不同步访问:

 Map<EnumKey, V> m = Collections.synchronizedMap(new EnumMap<EnumKey, V>(...));

答案 1 :(得分:3)

通常,在线程中使用非线程安全的类充满了许多问题。在您的特定情况下,假设在所有键都已分配了值(例如map.size() == TheEnum.values().length)后安全发布,我可以从EnumMap's code in Java 1.6的快速浏览中看到的唯一问题是put可能不永远反映在另一个线程中。但这只是真的,因为EnumMap的实施内部可能会在未来发生变化。换句话说,未来的变化可能会以更危险,更微妙的方式打破用例。

可以编写仍然包含数据竞赛的正确代码 - 但这很棘手。为什么不将实例包装在Collections.synchronizedMap

答案 2 :(得分:0)

您遇到的问题是线程可能看不到其他线程所做的更改,或者他们可能会看到部分更改。在java 5引入volatile之前,双重检查锁定被打破的原因相同。

如果你将EnumMap引用设置为volatile,它可能会有效,但即使那时我也不是100%确定,你可能需要EnumMap内部的内部引用是易变的,显然你不能做你自己的版本EnumMap的。