并发集合的包含方法是无用的吗?
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 }
我对吗?
正如注释线程中所述:不, containsKey
不会以任何方式锁定条目,因此稍后调用get(key)
可能会返回null
。 也就是说,如果你只对布尔值感兴趣 – 是地图中的关键吗? – 之后您不需要获取密钥,然后containsKey
就可以了。
另外, Map
接口需要containsKey
,所以它不像它不会在那里。
这不是无用的。 想象一下, get
的结果不需要做任何事情。 在这种情况下, containsKey
和get
(并遭受)相同的问题。
然而,正如Voo在评论中指出的那样,代码通常可以用putIfAbsent
(用于表示更大的primefaces操作)来编写。
它只是没有 (因为它本身不能)创建更大的primefaces上下文 。 也就是说,没有什么能阻止其他线程在containsKey
和get
之间对concurrentHashMap
进行操作。 密切关注javadoc的合同 :
…即使所有[个别]操作都是线程安全的,检索操作也不需要锁定,并且没有任何支持以阻止所有访问的方式锁定整个表 …
检索操作(包括get)通常不会阻塞,因此可能与更新操作(包括put和remove)重叠。 检索[例如containsKey或get]反映了最近完成的更新操作的结果 ……
对象是“线程安全的”并且在并发上下文中正确使用所述对象之间存在差异。
快乐的编码。