【问题标题】:Does java.util.concurrent.ConcurrentHashMap.putIfAbsent need to be in a syncronized block?java.util.concurrent.ConcurrentHashMap.putIfAbsent 是否需要在同步块中?
【发布时间】:2013-08-20 08:32:30
【问题描述】:

我正在尝试追踪比赛条件,所有迹象似乎都指向ConcurrentHashMap.putIfAbsent()。是否有可能如果 2 个线程在具有相同键的空映射上调用 putIfAbsent(),那么两者都可以进行查找以查看该键尚不存在,因此两个线程都尝试添加它?出于某种原因,当我第一次开始使用putIfAbsent() 时,我认为呼叫不需要同步。但是现在我看不出如果时机合适,它将如何阻止两个线程添加它们的值。我无法在生产之外重现此内容。

谢谢

【问题讨论】:

  • 你能贴一个代码sn-p吗?魔鬼在细节中。

标签: java multithreading concurrency synchronization concurrenthashmap


【解决方案1】:

任何并发集合的操作都不需要使用同步。

这是设计使然,实际上锁定集合对其他操作没有影响。 (除非它们也被锁定)在这种情况下,它会使它们变慢。

是否有可能如果 2 个线程在具有相同键的空映射上调用 putIfAbsent() 时,两者都可以进行查找以查看该键尚不存在,因此两个线程都尝试添加它?

两者都可以尝试,但只有一个会成功。不可能让两个线程看起来都成功了。

由于某种原因,当我第一次开始使用 putIfAbsent() 时,我认为调用不需要同步。

没有。

但现在我看不出如果时机合适,它将如何阻止两个线程添加它们的值。

它在代码中执行CAS operation,这意味着只有一个操作可以成功,线程会知道是哪一个。 CAS 操作不需要锁定,因为它使用底层汇编指令来执行此操作。实际上,您通常会使用 CAS 操作来实现锁定,而不是相反。

【讨论】:

  • 我仍然希望能够执行插入的线程 putIfAbsent 调用返回空值。而对于另一个线程,putIfAbsent 会返回进入映射的其他线程值?
  • @Brian 正确,如果您执行 get(),您将看到您期望的值。
【解决方案2】:

是否有可能如果 2 个线程在具有相同键的空映射上调用 putIfAbsent,则两者都可以进行查找以查看该键尚不存在,因此两个线程都尝试添加它?

不符合putIfAbsent() 的文档:

如果指定的键尚未与值关联,则将其与给定值关联。这相当于

if (!map.containsKey(key))
    return map.put(key, value);
else
    return map.get(key);

除了动作是原子执行的

这意味着两个线程都不可能尝试插入键值对。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    • 2015-02-04
    • 1970-01-01
    相关资源
    最近更新 更多