このスニペットをスレッドセーフにする最善の方法は何ですか?
private static final Map<A, B> MAP = new HashMap<A, B>();
public static B putIfNeededAndGet(A key) {
B value = MAP.get(key);
if (value == null) {
value = buildB(...);
MAP.put(key, value);
}
return value;
}
private static B buildB(...) {
// business, can be quite long
}
私が考えることができるいくつかの解決策は次のとおりです。
- を使用することもできますが
ConcurrentHashMap
、よく理解していれば、アトミックおよび操作がスレッドセーフになるだけです。つまり、特定の値に対してメソッドが 1 回だけ呼び出されることは保証されません。put
get
buildB()
- を使用できます
Collections.synchronizedMap(new HashMap<A, B>())
が、最初のポイントと同じ問題が発生します。 putIfNeededAndGet()
メソッド全体を設定することもsynchronized
できますが、非常に多くのスレッドがこのメソッドに一緒にアクセスする可能性があるため、非常にコストがかかる可能性があります。- 二重チェックのロック パターンを使用できますが、関連する順不同の書き込みの問題がまだあります。
他にどのような解決策がありますか?
これが Web で非常に一般的なトピックであることは知っていますが、明確で完全で実際に機能する例をまだ見つけていません。