0

私はCassandraと協力し、Datastax Javaドライバを使用しています。準備した文をキャッシュして再利用しようとしています。"putIfAbsent"はCHMでどのように機能しますか?

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

    public BoundStatement getStatement(String cql) { 
    Session session = TestUtils.getInstance().getSession(); 
    PreparedStatement ps = holder.get(cql); 
    // no statement is cached, create one and cache it now. 
    if (ps == null) { 
     holder.putIfAbsent(cql, session.prepare(cql)); 
    } 
    return ps.bind(); 
    } 

Prepared StatementおよびBoundStatementのdatastax java driverです。

このgetStatementメソッドは複数のスレッドで呼び出されるため、スレッドセーフであることを確認する必要があります。私はJava 7で作業しています。

2つの同じcqlプリペアドステートメントを取得すると、putIfAbsentはどうなりますか?コードスレッドは安全で、競合状態はありませんか?

アップデート: -

public BoundStatement getStatement(String cql) { 
    Session session = TestUtils.getInstance().getSession(); 
    PreparedStatement ps = holder.get(cql); 
    // no statement is cached, create one and cache it now. 
    if (ps == null) { 
     synchronized (this) { 
     ps = holder.get(cql); 
     if (ps == null) { 
      ps = session.prepare(cql); 
      holder.put(cql, ps); 
     } 
     } 
    } 
    return ps.bind(); 
    } 
+0

今はどうですか?それは正しいか? – john

+0

はい、そうです。 – Holger

答えて

1

あなたのコードは、任意のcqlパラメータに二回(またはそれ以上)と呼ばれてsession.prepare(cql)につながることができます競合状態を持っています。この場合、putIfAbsentは通常のputよりも利点がありません。

は、Java 8の上にいた場合、あなたは

PreparedStatement ps = holder.computeIfAbsent(cql, key -> session.prepare(key)); 
+0

誰かが 'putIfAbsent'のための大きなユースケースを持っている人は、それを聞きたいと思います。 – Kayaman

+0

私はまだJava 7を使用しています。Java 7でこの問題を回避するにはどうすればよいですか? – john

+0

@david正直言って私はJava 7のための非常に洗練されたソリューションを持っていません。あなたは 'get/check for null/put'部分を手動でロックする必要があります。 – Kayaman

1

との重複を作成することなく、効率的にこれを書くことができますが、実際に競合状態を持っていますが、それは続けるとして、あなたのputIfAbsentは、おそらくまだ少し良いput純粋より古いステートメントなので、実際には2つのインスタンスが存在することはありません。競争状態の場合にのみ現れるので、利点は小さい。

Double-checked lockingのようです。本当に必要な場合は、再初期化の前後に同期ブロックを置くだけです。

PreparedStatementが変更可能であるため、私はキャッシュに懐疑的です。同じcqlに複数のインスタンスが必要な場合があります。これも実行可能ですが、適切に取得してリリースする必要があります。

+0

準備されたステートメントをキャッシュする私の考えは、[this](http://stackoverflow.com/questions/22915840/re-using-preparedstatement-when-using-datastax-cassandra-driver)から来ました。それ以外の場合は毎回警告を発し続けます。 – john

+0

私はsynchronizedブロックで質問を更新しました。それはあなたが意味するものですか? – john

+0

@davidはい、同期ブロックが正常に見えます。変更可能性について、[この回答](http://stackoverflow.com/a/22917891/581205)は良く見えます(私はカサンドラについて何も知らない)。 Btw。、元の競合状態は、すべてのリスクが効率の警告を得ているので、受け入れられます。 – maaartinus

関連する問題