我正在尝试追踪比赛条件,所有迹象似乎都指向ConcurrentHashMap.putIfAbsent()
. 是否有可能,如果 2 个线程putIfAbsent()
使用相同的键调用空映射,则两者都可以进行查找以查看该键尚不存在,因此两个线程都尝试添加它?出于某种原因,当我第一次开始使用时,putIfAbsent()
我认为呼叫不需要同步。但是现在我看不出如果时机合适,它将如何阻止两个线程添加它们的值。我无法在生产之外重现这一点。
谢谢
我正在尝试追踪比赛条件,所有迹象似乎都指向ConcurrentHashMap.putIfAbsent()
. 是否有可能,如果 2 个线程putIfAbsent()
使用相同的键调用空映射,则两者都可以进行查找以查看该键尚不存在,因此两个线程都尝试添加它?出于某种原因,当我第一次开始使用时,putIfAbsent()
我认为呼叫不需要同步。但是现在我看不出如果时机合适,它将如何阻止两个线程添加它们的值。我无法在生产之外重现这一点。
谢谢
任何并发集合的操作都不需要使用同步。
这是设计使然,实际上锁定集合对其他操作没有影响。(除非它们也被锁定)在这种情况下,它会使它们变慢。
如果 2 个线程使用相同的键在空映射上调用 putIfAbsent() 是否有可能两者都可以进行查找以查看该键尚不存在,因此两个线程都尝试添加它?
两者都可以尝试,但只有一个会成功。两个线程不可能看起来已经成功。
出于某种原因,当我第一次开始使用 putIfAbsent() 时,我认为调用不需要同步。
它没有。
但是现在我看不出如果时机合适,它将如何阻止两个线程添加它们的值。
它在代码中执行CAS 操作,这意味着只有一个操作可以成功,线程将知道哪一个操作。CAS 操作不需要锁定,因为它使用底层汇编指令来执行此操作。事实上,您通常会使用 CAS 操作来实现锁,而不是相反。
是否有可能,如果 2 个线程
putIfAbsent
使用相同的键调用空映射,则两者都可以进行查找以查看该键尚不存在,因此两个线程都尝试添加它?
不根据以下文档putIfAbsent()
:
如果指定的键尚未与值关联,则将其与给定值关联。这相当于
if (!map.containsKey(key))
return map.put(key, value);
else
return map.get(key);
除了动作是原子执行的。
这意味着两个线程都不可能尝试插入键值对。