使此代码段线程安全的最佳方法是什么?
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
,但如果我很好理解,它只是使原子put
和get
操作线程安全,即它不确保buildB()
为给定值仅调用一次的方法。 - 我可以使用
Collections.synchronizedMap(new HashMap<A, B>())
,但我会遇到与第一点相同的问题。 - 我可以设置整个
putIfNeededAndGet()
方法synchronized
,但是我可以让很多线程一起访问这个方法,所以它可能会非常昂贵。 - 我可以使用双重检查锁定模式,但仍然有相关的 out-of-order writes issue .
我还有哪些其他解决方案?
我知道这是网络上很常见的话题,但我还没有找到一个清晰、完整且有效的示例。
最佳答案
使用 ConcurrentHashMap 和你用过的惰性初始化模式
public static B putIfNeededAndGet(A key) {
B value = map.get(key);
if (value == null) {
value = buildB(...);
B oldValue = map.putIfAbsent(key, value);
if (oldValue != null) {
value = oldValue;
}
}
return value;
}
关于java - 仅本地图值不存在时才创建并放置一个 map 值,并获取它 : thread-safe implementation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19949731/