2016-11-27 4 views
1

私の下のメソッドのスレッドは安全ですか?このメソッドはSingletonクラスです。アトミック操作としてgetとputを使用して並行ハッシュマップスレッドを安全にする方法はありますか?

private static final Map<String, PreparedStatement> holder = new ConcurrentHashMap<>(); 

    public BoundStatement getStatement(String cql) { 
    Session session = TestUtils.getInstance().getSession(); 
    PreparedStatement ps = holder.get(cql); 
    if(ps == null) { // If "ps" is already present in cache, then we don't have to synchronize and make threads wait. 
     synchronized { 
      ps = holder.get(cql); 
      if (ps == null) { 
      ps = session.prepare(cql); 
      holder.put(cql, ps); 
      } 
     } 
    } 
    return ps.bind(); 
    } 

私はカサンドラと協力しdatastax Javaドライバを使用して、私は準備された文を再利用していると私はここでそれをキャッシュしています理由ですしています。 Prepared StatementおよびBoundStatement

私のgetStatementメソッドはスレッドセーフであれば(スレッドセーフであれば)、そのようなsynchronizedブロックを使用するより良い方法はありますか?これらの操作のスレッドセーフな他のデータ構造ですか?私は.putIfAbsentはJava7であるので、あなたがそれを使用できるJava 7

+0

ああ、申し訳ありませんが、それを逃した。 –

+0

あなたの質問のタイトルは少し離れています。 ConcurrentHashMapをスレッドセーフにする必要はありません。すでに、スレッドセーフです。あなたがここでやろうとしているのは、_own_コードをスレッドセーフにすることです。 –

+0

あなたは正しいと思います。 – john

答えて

1

で働いています:putIfAbsentはまだ内部的に同じ同期を使用しています

private static final ConcurrentHashMap<String, PreparedStatement> holder = new ConcurrentHashMap<>(); 

    public BoundStatement getStatement(String cql) { 
    Session session = TestUtils.getInstance().getSession(); 
    PreparedStatement ps = holder.get(cql); 
    if(ps == null) { // If "ps" is already present in cache, then we don't have to synchronize and make threads wait. 

     if (holder.putIfAbsent(cql, session.prepare(cql)) != null) { 
      // Someone else got there before, handle 
     } 
    } 
    return ps.bind(); 
    } 

注意。

+0

内側のブロックで何をすべきか?それをどう扱うか? – john

+0

内部ブロックとは、同じcqlを同時に2つ準備し、マップ内に1つだけ取得したことを意味します。気にしない場合は、ブロックを削除してください。そうした場合は、ログに記録するか、エラーを投げてください。 –

+1

注: 'putIfAbsent'は' ConcurrentHashMap'にあり、 'Map'ではありません。フィールド宣言を変更する必要があります。 –

1

memoizationを行う場合は、Java 7で最も簡単に実行できます。Guavaには、使用できるコンピューティングのCache実装があり、Mapインターフェイスには、Java 8にはcomputeIfAbsentメソッドがありますしかし、あなたは明らかにここで不運です。

アレクシーの回答のように、空のレースにオブジェクトを作成することができれば、それが最適な解決策です。できない場合、実装はスレッドセーフであり、合理的です。

これは二重チェックロックの形式ですが、この実装ではCHMのputgetのメソッドを使用して先発順序を保証しています。

関連する問題