Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 带有并发put/get的EnumMap_Java_Concurrentmodification_Enum Map - Fatal编程技术网

Java 带有并发put/get的EnumMap

Java 带有并发put/get的EnumMap,java,concurrentmodification,enum-map,Java,Concurrentmodification,Enum Map,我正在考虑在并发环境中使用EnumMap。然而,环境是非典型的,原因如下: EnumMap始终已满:当映射暴露于并发环境时,没有未映射的键 将只使用put()和get()操作(不迭代、不删除()等) 如果get()不能立即/有序地反映put()s,则完全可以接受 从我所能收集到的信息,包括相关的方法源代码,这似乎是一个安全的场景(不同于允许迭代)。有什么我可能忽略了的吗?直接从: 与大多数集合实现一样,EnumMap不同步。如果多个线程同时访问一个枚举映射,并且至少有一个线程修改该映射,则应

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

  • EnumMap始终已满:当映射暴露于并发环境时,没有未映射的键
  • 将只使用put()和get()操作(不迭代、不删除()等)
  • 如果get()不能立即/有序地反映put()s,则完全可以接受
从我所能收集到的信息,包括相关的方法源代码,这似乎是一个安全的场景(不同于允许迭代)。有什么我可能忽略了的吗?

直接从:

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

Map m=Collections.synchronizedMap(新的EnumMap(…);
直接从以下位置开始:

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

Map m=Collections.synchronizedMap(新的EnumMap(…);

您遇到的问题是,线程可能永远看不到另一个线程所做的更改,或者可能看到部分更改。这与Java5引入volatile之前双重检查锁定被破坏的原因相同


如果您使EnumMap引用不稳定,它可能会起作用,但即使这样,我也不能100%确定,您可能需要EnumMap中的内部引用是易变的,显然,如果不执行自己版本的EnumMap,您就无法做到这一点。

您遇到的问题是,线程可能永远看不到另一个线程所做的更改,或者可能会看到部分更改。这与Java5引入volatile之前双重检查锁定被破坏的原因相同


如果您将EnumMap引用设置为volatile,这可能会起作用,但即使这样,我也不能100%确定,您可能需要EnumMap中的内部引用是volatile的,显然,如果不执行自己版本的EnumMap,您就无法做到这一点。

一般来说,跨线程使用非线程安全类充满了许多问题。在您的特定情况下,假设在所有键都指定了值(例如
map.size()==thenum.values().length
)之后安全发布,从快速浏览中我可以看到的唯一问题是
put
可能永远不会反映在另一个线程中。但这仅仅是因为
EnumMap
实现的内部结构才是正确的,它在未来可能会发生变化。换句话说,未来的变化可能会以更危险、更微妙的方式破坏用例


编写仍然包含数据竞争的正确代码是可能的,但这很棘手。为什么不将实例包装在一个
集合中。synchronizedMap

一般来说,跨线程使用非线程安全类充满了许多问题。在您的特定情况下,假设在所有键都指定了值(例如
map.size()==thenum.values().length
)之后安全发布,从快速浏览中我可以看到的唯一问题是
put
可能永远不会反映在另一个线程中。但这仅仅是因为
EnumMap
实现的内部结构才是正确的,它在未来可能会发生变化。换句话说,未来的变化可能会以更危险、更微妙的方式破坏用例


编写仍然包含数据竞争的正确代码是可能的,但这很棘手。为什么不将实例包装在一个
集合中。synchronizedMap

事实上,基于特定JDK内部的假设并不是一件好事。请务必阅读下面Tim B的警告——我忘了添加它。具体地说,如果你把对象A放在一个线程中,然后在另一个线程中读取,你可能会看到A的部分视图。为了实现这一点,A本身必须是线程安全的,即使是不安全的发布。事实上,基于特定JDK内部的假设并不是一件好事。请务必阅读下面Tim B的警告——我忘了添加它。特别是,如果您将对象A放在一个线程中,并在另一个线程中读取它,您可能会读取A的部分视图。为了使其工作,A本身必须是线程安全的,即使是非安全发布的。在我描述的场景中没有不必要的副作用。当然,puts()不会以任何逻辑方式被确认,但它们不需要被确认:)在我描述的场景中没有不必要的副作用。当然,puts()不会以任何逻辑方式被确认,但它们不需要:)“线程可能永远看不到另一个线程所做的更改,或者可能看到部分更改。”-这是可以接受的;也就是说,一些put()可以被任意延迟(而另一些则不是),这不是问题。我正在公开一个具体的EnumMap实例,因此您对
volatile
的评论是不相关的。他们可能永远看不到更改。更重要的是,您放入映射中的
值只能在另一个线程开始查看时部分初始化!编译器/JVM在更改代码位方面有很大的自由。”线程可能永远看不到另一个线程或
 Map<EnumKey, V> m = Collections.synchronizedMap(new EnumMap<EnumKey, V>(...));