私が理解していれば、同時のシナリオでは何が起こるのか、そしてHashMapが適切かどうか(適切でないと広く知られているもの)ではないかという疑問があります。
このような非常に望ましくないシナリオでは、どのような種類の問題が発生するかを知る最も良い方法は、the source codeを分析することです。例えば、OpenJDKの1.6実装では:、この方法および属性に不在O同期機構において
public V More ...put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
以下の問題の1つ以上が発生することができる:
1)非決定リターン
ライン:スレッド1用
return oldValue;
結果が古い値とすることができる(糸1及び2つのコールの前に)、2またはnullであることができます。スレッド2のaddEntry(ハッシュ、キー、値、i)が完全に転送されているかどうかに依存します。もちろん、スレッド2と同じ問題です。
2)未定インデックスと重複キー
int i = indexFor(hash, table.length);
table.length上依存します。したがって、このハッシュの以前の値が存在するかどうかに応じて、別のスレッドのaddEntry(hash、key、value、i)の実行に応じて、両方の呼び出しでiインデックスが異なる可能性があります。
3)壊れたサイズと一貫性
put( "a"、...)を連続して呼び出しても、マップのサイズは変更されません(少なくともキー "a" )。しかし、2つのスレッドのrace conditionsに応じて、マップサイズの一貫性が損なわれる可能性があります。すなわち、keysetのサイズはマップサイズのサイズと異なります。 modCountが将来のputとgetの呼び出しを壊してしまう可能性があるため、キーをハッシュするために使用される他の変数。
質問のコメントでどのように適切に言われましたか。予想外の動作と内部構造の損傷により、同時シナリオでのマップの使用が完全に無効になりました。
号は、それをしません。 –
['HashMap'](https://docs.oracle.com/javase/9/docs/api/java/util/HashMap)のようにスレッドセーフでないと宣言されたコードを悪用すると、html)、行動の約束はなく、結果は予測できません。 'HashMap'ドキュメントの明快さと、あなたが[' ConcurrentHashMap'](https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/ConcurrentHashMap.html)を知っていることを考えると、あなたの質問は意味をなさない。 –
グリズリークマを華麗なドレスパーティーに招待しているのと同じです...あなたは何が起こるかを知る方法がなく、それはおそらく美しくないでしょう。 –