我阅读了所有关于Java ConcurrentHashMap用法的相反的内容。我希望我的问题将有助于澄清一些看起来简单的事情(带有最新的答案)。
我有一张这样的地图:
ConcurrentHashMap<Integer, ClassA> map = new ConcurrentHashMap<Integer, ClassA>()我使用ConcurrentHashMap来保证put和get操作线程的安全。我的ClassA有一些Integer/String属性和一个String集合。
现在我想知道如何安全地更新我的映射对象。如果我想通过添加一个新的字符串来创建一个方法来从我的map更新一个对象,我有类似这样的东西:
synchronized(map)
{
Collection<String> strings = map.get(id).getStrings();
if(!strings.contains(newString)) //strings can't be null
{
strings.add(newString);
}
}这段代码对于并发读/写是安全的吗?是否可以通过使用Java API以不同的方式完成此任务?
发布于 2015-01-23 07:18:51
您的答案中包含的内容不是完全的线程安全。它将替换键id的值,而不管旧值是什么。如果这对您的实现来说没问题,那么很好,但是replace(K key, V oldObj, V newObj)是替换ConcurrentMap中现有值的理想检查和设置方法。
在您的特定用例中,您将执行以下操作
ClassA oldObj = map.get(id);
ClassA newObject = new ClassA(oldObject, newValue);
return map.replace(id, oldObj, newObject);这可确保仅当前一个值为oldObj时才更新贴图。如果此代码块被具有不同newValue的不同线程调用,会发生什么情况?上面的代码只会让一个线程成功,而另一个线程将返回false。
发布于 2015-01-21 02:35:12
这是试图回答我自己的问题。这极大地启发了我找到的另一个问题答案:What is the preferred way to modify a value in ConcurrentHashMap?
如果我将ClassA设置为不可变,并以这种方式替换用于更新地图对象的代码:
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行之间。
https://stackoverflow.com/questions/28034244
复制相似问题