我已经深入研究了并发性,并且真的很难理解并发数据结构(即并发哈希图)中使用的一些设计。
我做了一些陈述,并以粗体显示了问题,请帮助我进行确认和回答。putIfAbsent
无法告知执行线程它实际上是用新值替换了键还是使用了现有的旧键,因为在两种情况下,它将返回旧值。那么“ putIfAbsent”的意义是什么,因为在大多数用例中我们实际上报告给最终客户/用户/有关操作结果,我知道这可能是概括性的,但仍然如此吗?我们大多数人可能会对Optional<Entry<K,V>> putIfAbsentAndReturnValueIfPut(K,V)
感到高兴,就像这样:-)?
我从putIfAbsent
原子中得到什么?如果我想报告最终用户的操作结果,我仍然需要使用同步访问。
想象以下结构:
Map<String, Integer> map = new ConcurrentHashMap<>();
Outcome someMethod(String key, Integer value) {
Integer returnedValue = map.putIfAbsent(key, value);// ??? so how do I know if I updated the value?
map.get(key).equals(value); // even if I compare, I am not in synchronized context
}
因此,如果我的密钥是UUID,则从长远来看,它可能会为新的地图条目生成重复的密钥,如何确保第二个线程在第一个使用相同的密钥之后调用“ put”:
答:操作发生,线程尝试放置。
B.手术结果
是已知的,因此第二个线程可以尝试重新生成新的UUID并尝试
再次放置还是通知呼叫者操作失败?
更新:谢谢大家,这是其中的日子之一。
最佳答案
通过检查putIfAbsent
的返回值,您始终可以找到该值是已添加还是已经存在:
final ConcurrentMap<String,Object> map = new ConcurrentHashMap<>();
final Object old = map.putIfAbsent("hello", "world");
if (old != null) {
// The value was already present and has not been modified
// by the call.
} else {
// There was no prior entry, and "world" has been assigned
// as value for key "hello"
}
请注意,如果地图实现接受
null
作为条目的值,则这仍然是模棱两可的。 (可能)由于这个原因,ConcurrentHashMap
不接受null
作为键和值:与Hashtable类似,但与HashMap不同,此类不允许将null用作键或值。
(如documentation中所述)