java - 仅本地图值不存在时才创建并放置一个 map 值,并获取它 : thread-safe implementation

标签 java multithreading map

使此代码段线程安全的最佳方法是什么?

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
}

以下是我能想到的几个解决方案:

  1. 我可以使用ConcurrentHashMap ,但如果我很好理解,它只是使原子 putget操作线程安全,即它不确保 buildB()为给定值仅调用一次的方法。
  2. 我可以使用 Collections.synchronizedMap(new HashMap<A, B>()) ,但我会遇到与第一点相同的问题。
  3. 我可以设置整个 putIfNeededAndGet()方法 synchronized ,但是我可以让很多线程一起访问这个方法,所以它可能会非常昂贵。
  4. 我可以使用双重检查锁定模式,但仍然有相关的 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/

相关文章:

java - Spring Boot 条件时间表

java - 线程不同时运行

java - 执行程序终止和关闭之间的区别

android - 在 github 上共享我的代码时,如何隐藏我的 Google Maps API key ?

map - Erlang 17推荐使用map replace record,但是mnesia如何支持map呢?

java - 在 Java 中获取系统正常运行时间

java - 有没有人使用本地 Maven 存储库中的 SnakeYAML 成功加载 YAML 文件?

java - 如何在 JLayer 覆盖的 JComponent 上激活工具提示?

Python:在第一个函数保持运行的同时运行第二个函数

arrays - 如何在 perl 中将数组 [key1,val1] 映射到哈希 { key1 => val1}?