ConcurrentHashMap は HashMap を拡張しません。どちらもハッシュ テーブルの実装ですが、同時実行性を提供するために、ConcurrentHashMap は HashMap とは非常に異なる内部構造を持っています。
Map を受け入れるメソッドに ConcurrentHashMap を提供すると、それが機能し、期待する同時動作が得られます。Map は一連のメソッドを記述する単純なインターフェースであり、ConcurrentHashMap はそのインターフェースを並行動作で実装します。
「同時」と「アトミック」には違いがあります。同時実行とは、複数の操作が同時に発生する可能性があり、Map (または私たちが話しているデータ構造) が常に有効な状態になることを意味します。これは、このマップで put()、get()、remove() などを呼び出す複数のスレッドを持つことができ、エラーが発生しないことを意味します (通常の HashMap でこれを試みると、そうでないためエラーが発生します)。同時実行を処理するように設計されています)。
アトミックとは、複数のステップを実行するアクションが、他のスレッドからは 1 つのステップを実行するように見えることを意味します - それらが完全に終了したか、まだ開始されていないことを認識している限り公平です。ConcurrentHashMap の場合、putIfAbsent() はそのような例の 1 つです。javadoc から、
指定されたキーがまだ値に関連付けられていない場合は、指定された値に関連付けます。これは次と同等です。
if (!map.containsKey(key)) {
return map.put(key, value);
else
return map.get(key);
ただし、アクションはアトミックに実行されます。
上記のコードを ConcurrentHashMap で試した場合、(Concurrent であるため) エラーは発生しませんが、他のスレッドがメイン スレッドとインターリーブし、エントリが上書きまたは削除されるという良い変更があります。ConcurrentMap は、アトミックな putIfAbsent() メソッドを指定して、実装が他のスレッドからの干渉なしにこれらのステップをアトミックに実行できるようにします。