java - 应该使用哪个 - ConcurrentHashMap putIfAbsent 或锁定映射

标签 java multithreading spring concurrency synchronization

我有一种情况,调用者希望根据当前实例(标识符)获取 bean 的对象。现在,如果当前实例存在 bean 对象,则不应再次创建它。所以有两种方法(我认为)可以做到这一点 -

1. Using putIfAbsent of ConcurrentHashMap

beanObject = objectFactory.get(); // this will create new instance every time
// even if not required
beanObject = beanMapForInstance.putIfAbsent(name, beanObject);
return beanObject;

或者

2. By Locking the map

beanObject = beanMapForInstance.get(name); // beanMapForInstance is a ConcurrentHashMap
if(beanObject == null){
    synchronized (beanMapForInstance) {
        beanObject = beanMapForInstance.get(name);
        if(beanObject == null){
            beanObject = objectFactory.getObject();
            beanMapForInstance.put(name, beanObject);
        }
    }
}
return beanObject;

在第一种方法中,每次都会创建新对象,因此我认为应该首选第二种方法。但是 findbugs 显示了在 ConcurrentHashMap 上执行同步的第二个选项存在问题,那么应该使用哪一个呢?

最佳答案

就您而言,别无选择:您无法锁定 ConcurrentHashMap。更准确地说,锁定 ConcurrentHashMap 无法按您的预期工作。它不会使您的操作成为线程安全的,因为 ConcurrentHashMap 中的线程安全操作不是通过同步对象本身来实现的。

引自Javadoc of ConcurrentHashMap :

This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details

如果您不想不必要地创建值,那么您可以使用 computeIfAbsent(如果您使用的是 JDK 8+),这样您就可以延迟实例化,直到真正需要它为止。

关于java - 应该使用哪个 - ConcurrentHashMap putIfAbsent 或锁定映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29667393/

相关文章:

Java Netbeans Jlabel 隐藏和显示

java - 如何将永久 CLASSPATH 添加到 Mac OS El Capitan 上的终端?

java - 不使用alt键的jButton快捷键

java - OSGi——这项技术有多成熟?

spring - Jooq、Spring 和 BoneCP 连接关闭两次错误

java - 将 .docx 转换为 html,我收到不可读的文本

c# - 通过基于类的当前实现直接枚举ConcurrentDictionary到正常的Dictionary,将它安全地复制吗?

c++ - 访问本地 linux 线程栈 (pthreads)

c - 使用信号量系统 V 的 Scanf 和 printf

java - Spring 配置文件和属性占位符异常