我阅读了所有与 Java ConcurrentHashMap 用法相反的内容。我希望我的问题能帮助澄清一些看起来很简单的事情(以及最新的答案)。
我有这样一张 map :
ConcurrentHashMap<Integer, ClassA> map = new ConcurrentHashMap<Integer, ClassA>()
我正在使用 ConcurrentHashMap 来保证 put 和 get 操作线程安全。我的 ClassA 有一些整数/字符串属性和一个字符串集合。
现在我想知道如何安全地更新我的映射对象。如果我想创建一个方法来通过添加新字符串来更新 map 中的对象,我有类似的东西:
synchronized(map)
{
Collection<String> strings = map.get(id).getStrings();
if(!strings.contains(newString)) //strings can't be null
{
strings.add(newString);
}
}
此代码对并发读/写是否安全?可以通过使用 Java API 以不同的方式完成吗?
最佳答案
您的答案不是完全线程安全的。无论旧值是什么,它都会替换键 id
的值。如果这对您的实现没问题,那么很好,但是 replace(K key, V oldObj, V newObj)
是替换 ConcurrentMap 中现有值的理想检查和设置 (CAS) 方法。
在您的特定用例中,您将执行以下操作
ClassA oldObj = map.get(id);
ClassA newObject = new ClassA(oldObject, newValue);
return map.replace(id, oldObj, newObject);
这确保只有在先前的值为 oldObj 时才会更新 map 。如果此代码块被具有不同 newValue
的不同线程调用,会发生什么情况?上面的代码只会让一个线程成功,另一个线程会返回false。
关于java - 如何执行并发安全的映射对象操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28034244/