6

ゲッターとセッターにアクセスする複数のスレッドがある場合、このコードは競合状態に陥りますか? set 操作中にゲッターが古いデータを取得してもかまいませんが、例外が発生したり、null になったりしない限りは問題ありません。

ConcurrentHashMap<String, Object> hashMap =
    new ConcurrentHashMap<String, Object> ();

void setByteArray(String string, byte[] byteArray) {
    hashMap.put(string, byteArray.clone());
}

byte[] getByteArray(String string) {
    return ((byte[]) hashMap.get(string)).clone();
}
4

4 に答える 4

5

これはほとんどスレッドセーフです (そのようなものがある場合)。hashMap足りないのは、フィールドを宣言することだけですfinal。これにより、マップの安全な公開が保証されます。

それ以外には、問題はありません(スレッドセーフに関して)。ConcurrentHashMapはスレッド セーフであるため、バイト配列の格納と取得も同様に行う必要があります。

また、バイト配列は常にコピーするため、マップに格納されているものを除いて、スレッド間で共有されることはありません。はConcurrentHashMapそれらをすべてのスレッドに安全に公開し、変更されることはない (事実上不変であることを意味する) ため、スレッドの安全性が保証されます。

最後に、コメントに基づいて、他のいくつかの側面に関する改良版を次に示します。

private final ConcurrentHashMap<String, Object> hashMap =
    new ConcurrentHashMap<String, Object> ();

void setByteArray(String string, byte[] byteArray) {
    hashMap.put(string, byteArray.clone());
}

byte[] getByteArray(String string) {
    Object result = hashMap.get(string);
    if(result == null)
        return null;
    else
        return ((byte[]) result).clone();
}

最初は のprivate修飾子であるためhashMap、サブクラスは他のオブジェクト (共有バイト配列など) を格納できません。

2 つ目は、ゲッターでの null チェックです。要件に基づいて、または別のものreturn null;に置き換えたい場合があります。throw new IllegalArgumentException();

于 2012-11-20T09:20:21.907 に答える
0

仕様http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.htmlConcurrentHashMapによると、スレッドセーフを扱っているので、問題ないようです。

于 2012-11-20T09:25:40.237 に答える
0

あなたのコードは、バイトのせいではなく、ConcurrentHashMap の使い方が原因で、スレッドセーフではありません。

マップにアイテムを追加するには、put() よりも putIfAbsent() を使用する必要があります。PutIfAbsent() は次と同等です

   if (!map.containsKey(key)){
      return map.put(key, value);
   }
   else {
       return map.get(key);
   }

(おそらく適切な同期ブロックまたはキーワードを使用)

put() だけを使用すると、マルチスレッド環境で既存の値を新しい値でオーバーライドする可能性があります。

于 2015-11-11T22:02:23.797 に答える
0

ConcurrentHashMapはそれに対処するように設定されているので、私の結論は、あなたはあなたの要件に問題がないはずだということです.

于 2012-11-20T09:21:22.873 に答える