4

並行ハッシュマップで現在の操作を安全に取得するにはどうすればよいですか?(putIfAbsentと同じもの)

悪い例、スレッドセーフではありません(状況を確認してから実行してください):

ConcurrentMap<String, SomeObject> concMap = new ...

//... many putIfAbsent and remove operations

public boolean setOption(String id, Object option){
   SomeObject obj = concMap.get(id);

   if (obj != null){
      //what if this key has been removed from the map?
      obj.setOption(option);
      return true;
   }

   // in the meantime a putIfAbsent may have been called on the map and then this
   //setOption call is no longer correct

   return false;
}

もう1つの悪い例は次のとおりです。

   public boolean setOption(String id, Object option){
       if (concMap.contains(id)){
           concMap.get(id).setOption(option);
           return true;
       }
       return false;
    }

ここで望ましいのは、追加、削除、および取得操作を同期してボトルネックにしないことです。

ありがとう

4

4 に答える 4

7

aのget()メソッドConcurrentHashMapはアトミックです。そのマップはnull値を許可しないため、get()「get if present」を実装します。結果がnull、の場合、キーは存在しませんでした。

于 2010-12-04T14:03:26.397 に答える
2

containsKey/を使用せずget、単に。を呼び出しますget。そのメソッドが返されるnull場合、キーは存在しませんでした。そうでない場合、キーは存在し、の時点でマップされていた値を取得しましたget

ドキュメントから:

指定されたキーがマップされている値を返します。このマップにキーのマッピングが含まれていない場合はnullを返します。

これはあなたの2番目の例がどのように見えるべきかです:

public boolean setOption(String id, Object option) {

    SomeObject opt = concMap.get(id);
    if (opt == null)
        return false;

    opt.setOption(option);
    return true;
}
于 2010-12-04T14:00:53.250 に答える
1

あなたがやろうとしているように見えるのは、複数の操作でキーをロックすることです。各操作のみがアトミックです。これらは、キーをロックする簡単な方法ではなく、マップをロックするだけです。

ただし、「キーを削除した場合」の場合は、setOptionが呼び出されるまで削除操作を遅らせるだけです。結果は同じである必要があります。

あなたは解決する必要がないかもしれない問題を解決しようとしているようです。キーが削除された後、またはキーが削除されるのを待っている間にsetOptionを呼び出すことが悪い理由を説明していません。

于 2010-12-04T14:24:56.050 に答える
0

ConcurrentMapの単一のキーで複数の操作を実行する必要がある場合は、いずれかの ロックストライピング手法を使用して競合を減らすことができます。Guavaフレームワークの例を次に示します。

   private Striped<Lock> lock;
    public boolean setOption(String id, Object option) {
      try {
        Lock lock = concMap.get(id);
        lock.lock();
          if (concMap.contains(id)){
          concMap.get(id).setOption(option);
       return true;
   }
   return false;
        } finally {
         lock.unlock();
        }
    }

または、Java 8:ConcurrentMap.computeは新しいアトミックメソッドであるため、キーでどのように実行されるかを確認してください。

    concMap.compute(keyId, (key, value) -> {
    dosmth; ... return key;  });

ps考えられるバリエーションは、ConcurrentMap.computeIfPresent()などです。

于 2016-04-13T18:39:01.830 に答える