4

競合状態を追跡しようとしていますが、すべての兆候がConcurrentHashMap.putIfAbsent(). 2 つのスレッドが同じキーを使用して空のマップを呼び出した場合putIfAbsent()、両方がルックアップを実行してキーがまだ存在しないことを確認できるため、両方のスレッドがそれを追加しようとする可能性はありますか? なんらかの理由で、私が最初に使い始めたときputIfAbsent()、通話を同期する必要があるとは思いませんでした。しかし、タイミングが正しかった場合、両方のスレッドが値を追加するのをどのように防ぐことができるかわかりません。生産外でこれを再現することはできませんでした。

ありがとう

4

2 に答える 2

9

同時収集の操作はすべて、synchronized を使用する必要はありません。

これは仕様によるものであり、実際にコレクションをロックしても他の操作には影響しません。(それらもロックされていない限り)その場合、速度が低下します。

2 つのスレッドが同じキーを使用して空のマップで putIfAbsent() を呼び出した場合、両方がルックアップを実行してキーがまだ存在しないことを確認できるため、両方のスレッドがそれを追加しようとする可能性はありますか?

どちらも試すことができますが、成功するのは 1 つだけです。2 つのスレッドが成功したように見えることはありません。

最初に putIfAbsent() を使い始めたとき、何らかの理由で、呼び出しを同期する必要があるとは思いませんでした。

そうではありません。

しかし、タイミングが正しかった場合、両方のスレッドが値を追加するのをどのように防ぐことができるかわかりません。

コード内でCAS 操作を実行します。つまり、成功できる操作は 1 つだけであり、スレッドはどの操作かを認識します。CAS 操作は、基礎となるアセンブリ命令を使用してこれを実行するため、ロックする必要はありません。実際、通常は、その逆ではなく、CAS 操作を使用してロックを実装します。

于 2013-08-20T08:36:13.127 に答える
3

2 つのスレッドが同じキーを使用して空のマップを呼び出した場合putIfAbsent、両方がルックアップを実行してキーがまだ存在しないことを確認できるため、両方のスレッドがそれを追加しようとする可能性はありますか?

のドキュメントによらないputIfAbsent():

指定されたキーがまだ値に関連付けられていない場合は、指定された値に関連付けます。これは、

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

ただし、アクションはアトミックに実行されます。

これは、両方のスレッドがキーと値のペアを挿入しようとすることができないことを意味します。

于 2013-08-20T08:36:25.163 に答える