java - ConcurrentHashMap computeIfAbsent

标签 java multithreading concurrency

Java 8 中引入了一个新的 computeIfAbsent API。 ConcurrentHashMap's impelementation of it 的 javadocs状态:

If the specified key is not already associated with a value, attempts to compute its value using the given mapping function and enters it into this map unless null. The entire method invocation is performed atomically, so the function is applied at most once per key. Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this map.

那么,在 key 已经存在且不需要计算的情况下,锁定此实现有何意义?整个方法 computeIfAbsent 是否如文档中所述同步,即使不需要计算或仅同步映射函数调用以防止调用函数两次?

最佳答案

执行ConcurrentHashMap非常复杂,因为它专门设计用于允许并发可读性,同时最大限度地减少更新争用。在一个非常高的抽象层次上,它被组织为一个分桶哈希表。所有读取操作都不需要锁定,并且(引用 javadoc)“不支持以阻止所有访问的方式锁定整个表”。为了实现这一点,内部设计非常复杂(但仍然优雅),键值映射保存在节点中,节点可以以各种方式(例如列表或平衡树)排列,以利用细粒度锁。如果您对实现细节感兴趣,您还可以查看 source code .

尝试回答您的问题:

So, what does it say about locking of this implementation in case when the the key already exists and the computation is unneeded?

可以合理地认为,与任何读取操作一样,不需要锁定来检查键是否已经存在并且不需要执行映射函数。

Is the whole method computeIfAbsent synchronized as stated in docs even if no calculation is needed or just the mapping function call is synchronized to prevent calling the function twice?

不,该方法在锁定方面不是同步,但从调用者的角度来看,它是原子执行的(即映射函数最多应用一次)。如果未找到键,则必须使用映射函数计算的值执行更新操作,并且在调用该函数时涉及某种锁定。可以合理地认为这种锁定是非常细粒度的并且只涉及表的很小一部分(嗯,必须存储 key 的特定数据结构)这就是原因(引用 javadoc,强调我的) 一些 其他线程尝试的更新操作可能在计算过程中被阻止”

关于java - ConcurrentHashMap computeIfAbsent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26481796/

相关文章:

java - 拦截并修改发往第三方应用程序的鼠标事件?

c - Teamcenter ITK 中的多线程

java - 并发变量修改 : cannot fully understand this example

java - Struts ajax 404错误

java - 在Java中模拟具有多个服务器的单个队列

java套接字如何从两个不同的线程发送数据

c# - 在同一程序的多个实例之间同步

java - 如何知道 ScheduledExecutorService 何时完成

java - 创建表类作为单例

java - Spring Security 3.1 身份验证 ProviderManager 抛出 NotSerializableException