2017-09-19 9 views
1

オブジェクト(HashMapやArrayListやPOJOなど)を常に1つの(同じ)スレッドで変更するときのスレッド安全性を達成するための一般的なアプローチ複数のスレッドでアクセスできますか?Java:1つのスレッドでオブジェクトを修正し、複数のスレッドを読み取る

ハッシュマップは私にとっては最も興味深いですが、私は一般的なアプローチが必要です。

揮発性にするには十分ですか?

ありがとうございました。

+1

いいえ、volatileは十分ではありません。変数が再割り当てされたときにのみ同期を出すので、マップ/リストが1つでもない場合はほとんどありません。 'java.util.concurrent'の' ReadWriteLock'のような内部ロックか外部ロックが必要です。特定のトレードオフを課すことにも注意してください。それぞれのjavadocの詳細。 –

答えて

1

多分あなたはConcurrentHashMapを見てください。 ConcurrentHashMapの

がAbstractMapの

を拡張

パブリッククラスのConcurrentMap、シリアライズ

回収の及び更新のための高予想同時実行の完全な同時実行をサポートするハッシュテーブルを実装します。このクラスは、Hashtableと同じ機能仕様に従い、Hashtableの各メソッドに対応するメソッドのバージョンを含みます。ただし、すべての操作がスレッドセーフであっても、検索操作ではロックが必要なく、すべてのアクセスを妨げるようにテーブル全体をロックするためのサポートはありません。このクラスは、スレッドの安全性に依存するが同期の詳細に依存しないプログラムでは、Hashtableと完全に相互運用可能です。

一般に、取得操作(getを含む)はブロックされないため、更新操作(putおよびremoveを含む)と重複する可能性があります。取得は、直前に完了した更新操作の結果を反映します。 (より正式には、指定されたキーの更新操作は、更新された値を報告しているそのキーの(非null)検索との発生前関係を保持します)。putAllやclearなどの集計操作では、いくつかのエントリだけの。同様に、Iterator、Spliterators、およびEnumerationsは、イテレータ/列挙の作成時または生成時のある時点でハッシュテーブルの状態を反映する要素を返します。それらはConcurrentModificationExceptionをスローしません。ただし、イテレータは一度に1つのスレッドのみが使用するように設計されています。 size、isEmpty、containsValueなどの集約ステータスメソッドの結果は、通常、マップが他のスレッドで同時更新を受けていない場合にのみ有用であることに注意してください。さもなければ、これらの方法の結果は、監視または推定目的には適切であるが、プログラム制御には不十分な過渡状態を反映する。ここ

詳細情報: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html

それはprogrammaticalyまさに古典ハッシュマップのように振る舞います。

1

一般的なアプローチは実装が容易ではなく、多くの努力が必要ですが、それでもやりすぎると問題が起こります。ですから、Gomoku7が提案するConcurrentHashMapが最善の策です。

一般的なアプローチでは、ロックに基づいた実装が必要です。更新の前にオブジェクトをロックし、後でロックを解除する必要があります。 Javaには異なるtypes of locksがあります。だから、必要に応じてロックを選んだ。

  1. Final

    はあなたの友人であることが必要でない限り
  2. 避けては一時的な変数
  3. 使用ExecutorsFork/Join可能
を作成し、可能な場合は、オブジェクトに finalを行い、オブジェクトを変化させません:いくつかのヒントがあります。
関連する問題