1

EnumMap並行環境での使用を検討しています。ただし、環境は異例です。理由は次のとおりです。

  • EnumMap常にいっぱいです: マップが並行環境に公開されている場合、マップされていないキーはありません
  • put()and操作のみget()が使用されます (反復なし、 noremove()など)。
  • への呼び出しが即時または秩序あるget()への呼び出しを反映していない場合は、完全に許容されます。put()

関連するメソッドのソース コードを含め、私が収集できたものから、これは安全なシナリオのようです (反復が許可されている場合とは異なります)。私が見落としている可能性のあるものはありますか?

4

3 に答える 3

4

JavaDocから直接:

ほとんどのコレクションの実装と同様に、EnumMap は同期されません。複数のスレッドが同時に enum マップにアクセスし、スレッドの少なくとも 1 つがマップを変更する場合は、外部で同期する必要があります。これは通常、enum マップを自然にカプセル化するオブジェクトを同期することによって実現されます。そのようなオブジェクトが存在しない場合は、Collections.synchronizedMap(java.util.Map<K, V>)メソッドを使用してマップを「ラップ」する必要があります。これは、偶発的な非同期アクセスを防ぐために、作成時に行うのが最適です。

 Map<EnumKey, V> m = Collections.synchronizedMap(new EnumMap<EnumKey, V>(...));
于 2014-01-21T11:44:46.947 に答える
4

一般に、スレッド間でスレッドセーフでないクラスを使用すると、多くの問題が発生します。あなたの特定のケースでは、すべてのキーに値が割り当てられた後に安全な公開を想定すると ( など)、 Java 1.6 の のコードをmap.size() == TheEnum.values().length一目見ただけでわかる唯一の問題は、 aが別のスレッドに反映されない可能性があることです。しかし、これは の実装の内部が原因であり、将来変更される可能性があるためです。言い換えれば、将来の変更は、より危険で微妙な方法でユース ケースを壊す可能性があります。EnumMapputEnumMap

データ競合を含む正しいコードを作成することは可能ですが、注意が必要です。インスタンスを でラップしないのはなぜCollections.synchronizedMapですか?

于 2014-01-21T11:46:24.163 に答える
1

あなたが抱えている問題は、スレッドが別のスレッドによって行われた変更をまったく認識しないか、部分的に加えられた変更を認識できることです。Java 5 が volatile を導入する前に、ダブルチェックロックが壊れていたのと同じ理由です。

EnumMap 参照を揮発性にするとうまくいくかもしれませんが、それでも 100% 確信が持てません。

于 2014-01-21T11:46:14.873 に答える