1. ホーム
  2. java

[解決済み] ConcurrentHashMapの値の反復はスレッドセーフか?

2022-04-23 18:22:37

質問

のjavadocでは ConcurrentHashMap は以下の通りです。

検索操作(getを含む)は一般にブロックされないので、更新操作(putやremoveを含む)と重なる場合があります。検索は、その開始時に保持されている直近に完了した更新操作の結果を反映する。putAllやclearのような集約操作の場合、同時取得は一部の項目のみの挿入または削除を反映することがあります。同様に、イテレータと列挙は、イテレータ/列挙の作成時または作成以降のある時点におけるハッシュテーブルの状態を反映した要素を返します。これらはConcurrentModificationExceptionを投げない。 ただし、イテレータは一度に1つのスレッドのみが使用するように設計されています。

どういうことですか?2つのスレッドで同時にマップを反復処理しようとするとどうなるのでしょうか?反復処理中にマップに値を入れたり、削除したりするとどうなりますか?

解決方法は?

<ブロッククオート

どういう意味ですか?

つまり、あなたが取得した各イテレータは ConcurrentHashMap は1つのスレッドで使用するように設計されており、他のスレッドに渡してはいけません。これには、for-eachループが提供する構文上の糖分が含まれます。

<ブロッククオート

2つのスレッドで同時にマップを反復処理しようとするとどうなるのでしょうか?

それぞれのスレッドが独自のイテレータを使用する場合は、期待通りに動作します。

<ブロッククオート

イテレート中にマップに値を入れたり、削除したりするとどうなるのでしょうか?

このようなことをしても、物事が壊れないことが保証されています(それは、quot;concurrent" の内容の一部です)。 ConcurrentHashMap を意味します)。しかし、あるスレッドが、他のスレッドが実行したマップの変更を(マップから新しいイテレータを得ることなく)見ることができるという保証はない。イテレータは、それが作成された時点のマップの状態を反映することが保証されています。それ以降の変更はイテレータに反映されるかもしれないが、反映される必要はない。

結論から言うと、次のような文は

for (Object o : someConcurrentHashMap.entrySet()) {
    // ...
}

は、ほぼ毎回問題なく(あるいは少なくとも安全に)見ることができます。