应该使用哪个 - ConcurrentHashMap putIfAbsent 或锁定地图
Which should be used - ConcurrentHashMap putIfAbsent or locking the map
我有一种情况,调用者希望根据当前实例(标识符)获取 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 上执行同步的第二个选项的问题,那么应该使用哪个?
先检查是否存在,然后再检查 putIfAbsent 怎么样?
beanObject = beanMapForInstance.get(name);
if (beanObject == null){
beanObject = beanMapForInstance.putIfAbsent(
name, objectFactory.get());
}
将在 99.99% 的时间工作,并且在非常罕见的竞争条件情况下,您调用冗余构造函数(除了性能方面的考虑,这对您来说显然不是问题)。
在你的情况下,别无选择:你无法锁定 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+,你可以延迟实例化直到真正需要它。
我有一种情况,调用者希望根据当前实例(标识符)获取 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 上执行同步的第二个选项的问题,那么应该使用哪个?
先检查是否存在,然后再检查 putIfAbsent 怎么样?
beanObject = beanMapForInstance.get(name);
if (beanObject == null){
beanObject = beanMapForInstance.putIfAbsent(
name, objectFactory.get());
}
将在 99.99% 的时间工作,并且在非常罕见的竞争条件情况下,您调用冗余构造函数(除了性能方面的考虑,这对您来说显然不是问题)。
在你的情况下,别无选择:你无法锁定 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+,你可以延迟实例化直到真正需要它。