首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何执行并发安全的映射对象操作?

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

Stack Overflow用户
提问于 2015-01-20 06:01:45
回答 2查看 130关注 0票数 3

我阅读了所有关于Java ConcurrentHashMap用法的相反的内容。我希望我的问题将有助于澄清一些看起来简单的事情(带有最新的答案)。

我有一张这样的地图:

代码语言:javascript
复制
ConcurrentHashMap<Integer, ClassA> map = new ConcurrentHashMap<Integer, ClassA>()

我使用ConcurrentHashMap来保证put和get操作线程的安全。我的ClassA有一些Integer/String属性和一个String集合。

现在我想知道如何安全地更新我的映射对象。如果我想通过添加一个新的字符串来创建一个方法来从我的map更新一个对象,我有类似这样的东西:

代码语言:javascript
复制
        synchronized(map)
        {
            Collection<String> strings = map.get(id).getStrings();
            if(!strings.contains(newString)) //strings can't be null
            {
                strings.add(newString);
            }
        }

这段代码对于并发读/写是安全的吗?是否可以通过使用Java API以不同的方式完成此任务?

EN

回答 2

Stack Overflow用户

发布于 2015-01-23 07:18:51

您的答案中包含的内容不是完全的线程安全。它将替换键id的值,而不管旧值是什么。如果这对您的实现来说没问题,那么很好,但是replace(K key, V oldObj, V newObj)是替换ConcurrentMap中现有值的理想检查和设置方法。

在您的特定用例中,您将执行以下操作

代码语言:javascript
复制
ClassA oldObj = map.get(id);
ClassA newObject = new ClassA(oldObject, newValue);
return map.replace(id, oldObj, newObject);

这可确保仅当前一个值为oldObj时才更新贴图。如果此代码块被具有不同newValue的不同线程调用,会发生什么情况?上面的代码只会让一个线程成功,而另一个线程将返回false。

票数 2
EN

Stack Overflow用户

发布于 2015-01-21 02:35:12

这是试图回答我自己的问题。这极大地启发了我找到的另一个问题答案:What is the preferred way to modify a value in ConcurrentHashMap?

如果我将ClassA设置为不可变,并以这种方式替换用于更新地图对象的代码:

代码语言:javascript
复制
        ClassA oldObject = map.get(id);
        ClassA newObject = new ClassA(oldObject, newValue);//this constructor copies the old one and add the newValue in my Collection of Strings
        map.put(id, newEvent);

它是线程安全的吗?我真的希望通过使用ConcurrentHashMap来保持代码的整洁和高效,我相信这个解决方案也会朝着同样的方向发展。我只是有点怀疑任何线程检索相同的对象,而另一个线程会在第2行和第3行之间。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28034244

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档