2017-01-26 5 views
0

私はJavaの並行処理で新しく、get(マップのように)でアクセスする必要のあるデータを保持するクラス(以下のサンプルコードでは2倍)を持っていますが、パフォーマンス上の理由から配列。java - 複数のオブジェクトへの並行更新

これはマルチスレッド環境で実行され、このインデックスは時々更新される必要があります。

public class ConcurrencySampleCode { 

    private static Object lock = new Object(); 

    private Map<String, Integer> map = ... 
    private double[] array = ... 

    public Double get(String id) { 
     synchronized (lock) { 
      Integer i = map.get(id); 
      if (i == null) { 
       return null; 
      } 
      return array[i]; 
     } 
    } 

    public void update() { 
     Map<String, Integer> tmpMap = updateMap(...); 
     double[] tmpArray = updateArray(...); 
     synchronized (lock) { // should be atomic 
      map = tmpMap; 
      array = tmpArray; 
     } 
    } 

} 

このコードが正しいかどうかわかりませんか?また、get関数でsynchronizedキーワードが必要ですか?

これを行うには良い方法がありますか?あなたの助け

+2

、[のConcurrentMap](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentMap.html)の実装があります。 –

+1

合意し、ConcurrentMapを使用してください。たとえば、ConcurrentHashMapはスレッドセーフで、ここでの処理よりも高速です。 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html –

+0

[こちらを読む](http://docs.oracle.com/javase/tutorial/essential/)並行性/ sync.html)。 – displayname

答えて

1

を理解していますが、すべてのスレッドが即座に更新された値を参照して確保するためにマップし、アレイ上volatileキーワードを使用する必要があります。ロックを静的にしたいとは思っていません。

java.util.concurrent.atomicパッケージをチェックアウトすることもできます。それは便利なスレッドセーフ変数をいくつか持っています。たとえば、マップと配列を独自のクラスに移動し、AtomicReferenceを使用してオブジェクトを格納することができます。コードに加え

public class ConcurrencySampleCode { 

    private AtomicReference<DoubleMap> atomicMap = new AtomicReference(new DoubleMap()); 

    //Inner class used to hold the map and array pair 
    public class DoubleMap { 
     private Map<String, Integer> map = ... 
     private double[] array = ... 
    } 

    public Double get(String id) { 
     DoubleMap map = atomicMap.get(); 
      ... 
    } 

    public void update() { 
     Map<String, Integer> tmpMap = updateMap(...); 
     double[] tmpArray = updateArray(...); 
     DoubleMap newMap = new DoubleMap(tmpMap, tmpArray); 
     atomicMap.set(newMap); 
    } 

} 
0

ため

おかげであり、並行プログラミングで起こったくさんあるが、例えば、あなたのupdate()方法が故障しています。現在の状態では、ThreadsConcurrencySampleCode.update()と呼び出すことができ、同期の開始前に本体の内部でupdateの両方の呼び出しが開始されます。これは、ラウンドロビンの終了後に更新呼び出しの最後のThreadに変更がないことを意味します新しく更新されたマップと配列の前のupdate呼び出しから。

長い物語は、使用しようとあなたのコードと間違って何もないConcurrentHashMap

+0

私が理解していないのは、ConcurrentHashMapと配列を原子的に更新する必要があるためです。助けてくれてありがとう – ogen

+0

@ogen並行パッケージはJavaで巨大です。あなたはその説明を読んで、それがあなたのニーズに合っているかどうかを見ることができます。 [リンク](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html) –

+0

OK、ドキュメント(特にセマフォ)を読んでいます。しかし、私のサンプルコードとConcurrentMapの関係は、マップと配列の両方の更新のアトミック性であるため、私は見ることができません。何かが足りない – ogen

関連する問題