これは間違っているようです。
static ConcurrentHashMap k; //multiple threads have access to k
X o = k.get("LL");
o.a = 6;
複数のスレッドが同時に k にアクセスし、k("LL") を取得した場合、k.put("ll",o) を使用せずに (oa = #) を更新すると、'o' または 'k' で同期されません。
これは間違っているようです。
static ConcurrentHashMap k; //multiple threads have access to k
X o = k.get("LL");
o.a = 6;
複数のスレッドが同時に k にアクセスし、k("LL") を取得した場合、k.put("ll",o) を使用せずに (oa = #) を更新すると、'o' または 'k' で同期されません。
ConcurrentMap には、キーと値のペアのアトミックな挿入/削除と置換を保証する条件付き操作があります。さらに、ConcurrentMap にアクセスすると、事前発生の関係が作成されるため、コードの順序について特定の保証を行うことができます。
提示されたコードでは、次の行:
X o = k.get("LL");
キー「LL」の現在の X 値にアクセスします。次の行は a プロパティを変更します。X の実装を知らなくても、これは Java であるため、ここにメソッド呼び出しがないことはわかっています。a プロパティが volatile としてマークされている場合に限り、"LL" で X にアクセスする後続のコードは a 値を 6 と見なします。 volatile でない場合、保証はまったくありません。特にSMP x86ボックスでは、一度に多くのスレッドが実行されていないため、おそらく6が表示されます。本番環境では、大きな NUMA ボックスでは、そうなる可能性は低くなります。可変性は、あらゆる種類の複雑さと困難をもたらします。
一般に、不変のキーと値を使用すると、マップの状態を簡単に判断できます。
ConcurrentHashMap は、値の取得がアトミックであることを保証しますが、取得した値で何をするかを制御することはできません。ハッシュマップの値を変更することは、ConcurrentHashMap のビューからは問題ありませんが、希望する動作にならない場合があります。スレッドセーフを確実にするには、スレッドにアクセスできる各スレッドが何をするのかを正確に考慮する必要があります。
値を ConcurrentHashMap に戻すことは冗長に思え、操作全体が安全になるわけではありません。同期の外部でオブジェクトを既に変更しています。
追加の同期が必要になる場合がありますが、詳細なコンテキストを見ないとわかりません。
簡単に言えば:
o.a=6
アトミック操作であり、すべてのスレッドが競合し、最後のスレッド設定が「勝ち」、値を上書きします。
より具体的には、 ConcurrentHashMap は、キーとそれに関連付けられた値の間のリンクが複数のスレッドを考慮して処理されることのみを保証します。つまり、 put と get はアトミックです。
これは、スレッドが値への参照を取得すると、その値の属性を変更することを妨げません!