繁体   English   中英

Java - 如何对并发 map 的值进行原子操作?

[英]Java - How to make operations on the value of a concurrent map atomic?

假设我在 class 中有以下字段:

ConcurrentHashMap<SomeClass, Set<SomeOtherClass>> myMap = new ConcurrentHashMap<SomeClass, Set<SomeOtherClass>>();

此 class 的一个实例在许多线程之间共享。

如果我想从与键关联的集合中添加或删除元素,我可以这样做:

Set<SomeOtherClass> setVal = myMap.get(someKeyValue);
setVal.add(new SomeOtherClass());

get操作是原子的,因此是线程安全的。 但是,不能保证在getadd指令之间,其他一些线程不会修改结构,干扰第一个执行。

使整个操作原子化的最佳方法是什么?

这是我想出的,但我不认为它非常有效(或者无法充分利用 Java 的结构):

我有一个 ReentrantLock 字段,所以我的 class 看起来像这样:

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());
}

我们的想法是,一旦我们确定没有其他人将访问我们正在尝试修改的 Set,我们就让 go 锁定。 但是,我不认为这是对ConcurrentMap的最佳利用,或者将锁、并发结构和synchronized块全部用于实现一个操作是很有意义的。

有没有关于 go 的最佳方法?

ConcurrentHashMap保证compute (或computeIfAbsentcomputeIfPresent )的整个方法调用是原子完成的。 因此,例如,您可以执行以下操作:

myMap.compute(someKeyValue, (k, v) -> {v.add(new SomeOtherClass()); return v;});

笔记:
使用compute类似于假设somKeyValue存在于 map 中的原始片段。 不过,使用computeIfPresent可能更安全。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM