java - 如何执行并发安全的映射对象操作?

标签 java multithreading concurrency concurrenthashmap

我阅读了所有与 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/

相关文章:

java - 如何在java中使用apache SPARK分割和过滤字符串

ios - 核心数据和竞争条件

java - 创建新对象是否有助于防止静态方法内的并发问题?

java - Java内存泄漏?用信号量实现哲学家就餐

java - 处理线程池并等待notifyALL()

java - Android 中如何设置 TextView 文本格式?

java - 错误消息 : No such element exception?

java - 如何从表中删除树节点及其子记录(无级联删除)?

java - 为什么我们使用标志来停止线程?

python - PyMySQL 选择不工作