java如何对并发映射的值进行原子化操作?
假设我在一个类中有以下字段:
ConcurrentHashMap<SomeClass, Set<SomeOtherClass>> myMap = new ConcurrentHashMap<SomeClass, Set<SomeOtherClass>>();
该类的一个实例在多个线程之间共享
如果要从与键关联的集合中添加或删除元素,可以执行以下操作:
Set<SomeOtherClass> setVal = myMap.get(someKeyValue);
setVal.add(new SomeOtherClass());
get
操作是原子的,因此是线程安全的。但是,不能保证在get
和add
指令之间,其他线程不会修改结构,从而干扰第一个线程的执行
让整个行动原子化的最好方法是什么
以下是我的想法,但我不认为这是非常有效的(或是最好地利用Java的结构):
我有一个ReentrantLock字段,所以我的类如下所示:
class A {
ReentrantLock lock = new ReentrantLock();
ConcurrentHashMap<SomeClass, Set<SomeOtherClass>> myMap = new ConcurrentHashMap<SomeClass, Set<SomeOtherClass>>();
}
然后方法调用如下所示:
lock.lock();
Set<SomeOtherClass> setVal = myMap.get(someKeyValue);
synchronized(setVal) {
lock.unlock();
setVal.add(new SomeOtherClass());
}
我们的想法是,一旦我们确定没有其他人会访问我们试图修改的集合,我们就会释放锁。然而,我不认为这是对ConcurrentMap
的最佳利用,也不认为使用锁、并发结构和synchronized
块来实现一个操作有多大意义
有更好的办法吗
# 1 楼答案
ConcurrentHashMap
保证compute
(或computeIfAbsent
或computeIfPresent
)的整个方法调用是原子化的。例如,你可以这样做:注意:
使用
compute
类似于假设somKeyValue
存在于映射中的原始片段。不过,使用computeIfPresent
可能更安全