并发集合的包含方法是无用的吗?

时间:2012-01-30 01:41:38

标签: java concurrency

if(concurrentHashMap.containKey(key))
{
    // oops, v has been removed in another thread right after current thread 
    // complete containKey calling
    Value v = concurrentHashMap.get(key); 
    // do something on v                  // null pointer exception
}

似乎并发集合的包含类方法是无用的,以解决上述问题:

Vaule v = concurrentHashMap.get(key);
if(v != null)
{
    // ok, hold v's reference
    // do something on v
}

我是对的吗?

2 个答案:

答案 0 :(得分:5)

这不是没用的。想象一下,get的结果不需要做任何事情。在这种情况下,containsKeyget都有(并遭受)同样的问题。

正如Voo在评论中指出的那样,代码通常可以用putIfAbsent(用于表示更大的原子操作)来编写。

只是(因为它本身不能)创建一个更大的原子上下文。也就是说, nothing 阻止其他线程在concurrentHashMapcontainsKey之间对get执行操作。密切关注contract from the javadoc

  

...即使所有 [个人] 操作都是线程安全的,但检索操作不需要锁定,并且没有任何支持以一种方式锁定整个表阻止所有访问 ...

     

检索操作(包括get)一般不会阻塞,因此可能与更新操作重叠(包括put和remove)。 检索[例如containsKey或get]反映了最近完成的更新操作的结果在发病时保留......

“线程安全”对象与在并发上下文中正确使用所述对象之间存在差异。

快乐的编码。

答案 1 :(得分:4)

如评论主题中所述:不,containsKey不会以任何方式锁定该条目,因此稍后调用get(key)可能会返回null。也就是说,如果你只对布尔值感兴趣 - 是地图中的关键吗? - 以后您不需要获取密钥,然后containsKey就可以了。

此外,containsKey界面还需要Map,所以不管怎样它都不会在那里。