並行性に戻ります。double checked lockingが機能するには、変数を として宣言する必要があることは明らかですvolatile。しかし、以下のようにダブルチェックロックを使用するとどうなるでしょうか。
class Test<A, B> {
private final Map<A, B> map = new HashMap<>();
public B fetch(A key, Function<A, B> loader) {
B value = map.get(key);
if (value == null) {
synchronized (this) {
value = map.get(key);
if (value == null) {
value = loader.apply(key);
map.put(key, value);
}
}
}
return value;
}
}
通常のHashMapではなく、実際にConcurrentHashMapである必要があるのはなぜですか? すべてのマップの変更はブロック内で行われ、コードは反復子を使用しないため、技術的には「同時変更」の問題はありません。synchronized
API の使用ではなく概念について質問しているため、 putIfAbsent/の使用を提案しないでください:) この API の使用がvsの主題に寄与しない限り。computeIfAbsentHashMapConcurrentHashMap
2016-12-30 更新
この質問は、以下の Holger によるコメントによって回答されました。「HashMap.get構造は変更されませんが、あなたの の呼び出しは変更されます。同期ブロックの外側で のput呼び出しがあるため、操作の不完全な状態が同時に発生していることがわかります。」ありがとう!getput