私は最近、HashMap を拡張して put メソッドを同期するクラスをコード ベースで見つけました。
ConcurrentHashMap を使用するよりも効率が悪いことを除けば、HashMap を拡張して put(K,V) のみを同期すると、どのような問題が発生する可能性がありますか?
get(K) が最新の値を返すかどうかは気にしないと仮定します (たとえば、スレッドが互いに上書きしても問題なく、マップの値が使用された場合に発生する可能性のある競合状態については気にしません)。自体をロックします)。
例:
public class MyMap<K,V> extends HashMap<K,V> {
//...
public synchronized void put(K key, V value) {
//...
}
//...
}
私の知る限り、HashMap は put メソッドでサイズ変更を行います。put はマップ インスタンス レベルで同期されるため、同時サイズ変更中に発生する問題は (おそらく) 発生しません。
上記の疑わしい仮定があっても、私の直感では、さらに問題が発生する可能性があることを示しています。それとも私はただ妄想的ですか?
更新: 皆さん、ありがとうございました。楽しくて啓発的でした。この特定のクラスの著者のオリジナルに会うことがあれば、彼の愚かさを詳細に説明することができます. :)
要約すると、 putAll は依然としてデータ構造をひどく台無しにし、恐ろしい無限ループ/データ競合状態に陥る可能性があります。get は、ハッシュマップの基になる内部データ構造に依存しており、同時に変更されている可能性があり、get プロセスが奇妙な動作をする原因となります。これは一般的に悪い考えです。少なくとも、作成者は代わりに Collections.synchronizedMap(Map) を使用できたはずです。
注: この記事の執筆時点で与えられた 3 つの回答はすべて実際には正しいですが、get() に関するものを正解として選びました。