簡體   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