0

私のクラスはConcurrentHashmap[String、immutable.List[String]]から拡張されています

そしてそれは2つの方法があります:

  def addEntry(key: String, newList: immutable.List[String]) = {
    ...
    //if key exist,appending the newList to the exist one 
    //otherwise set the newList as the value
  }

  def resetEntry(key: String): Unit = {
    this.remove(key)
  }

addEntryメソッドのスレッドを安全にするために、私は試しました:

this.get(key).synchronized{
  //append or set here
}

ただし、キーが存在しない場合はnullポインター例外が発生し、同期前にputIfAbsent(key、new immutable.List())を使用すると、putIfAbsentの後、同期ブロックに入る前にキーが機能しなくなります。キーはresetEntryによって削除される場合があります。

addEntryとresetEntryの両方の同期メソッドは機能しますが、ロックが大きすぎます

だから、私は何ができますか?

ps。この投稿は、ConcurrentHashMapスレッド内のBigDecimalの更新を安全にする方法と類似していますが、plzは、一般的なガイド以外のコーディング方法を理解するのに役立ちます

--update-- checkout https://stackoverflow.com/a/34309186/404145、ほぼ3年以上後にこれを解決しました。

4

3 に答える 3

1

エントリを削除する代わりに、単純にクリアできますか? 同期リストを引き続き使用して、原子性を確保できます。

  def resetEntry(key: String, currentBatchSize: Int): Unit = {
    this.get(key).clear();
  }

これは、各キーにエントリがあるという前提で機能します。たとえば、クリアとしても機能this.get(key)==nullする新しいを挿入したい場合。sychronizedList

于 2012-07-16T16:11:06.760 に答える
0

CAS (Compare and Swap) プロセスに触発された方法を試すことができます。

(私のScalaはまだ初期段階にあるため、疑似Java-scalaコードで)

def addEntry(key: String, newList: immutable.List[String]) = {
    val existing = putIfAbsent(key, newList); 
    if (existing != null) {
       synchronized(existing) {
           if (get(key) == existing) { // ask again for the value within the synchronized block to ensure consistence. This is the compare part of CAS
                return put(key,existing ++ newList); // Swap the old value by the new
           } else {
               throw new ConcurrentModificationException(); // how else mark failure?
           }
       }
    }
    return existing;
}
于 2012-07-16T17:13:56.673 に答える