Java ConcurrentHashMap中的put()方法也是原子的吗?
在Java ConcurrentHashMap中的put()方法也是原子的吗?,java,concurrency,Java,Concurrency,在ConcurrentHashMap中,putIfAbsent()是原子的。我的问题是ConcurrentHashMap中的方法put()也是原子的?文档中没有明确说明put或get是原子的。然而,缔约国指出: 检索反映了最近完成的更新操作在开始时的结果。(更正式地说,给定键的更新操作与报告更新值的该键的任何(非null)检索具有“发生在前”关系。) 这意味着如果一个线程使用相同的键执行put,另一个线程执行get,那么get将看到“在put之前”状态或“在put之后”状态。这实际上意味着,ge
ConcurrentHashMap
中,putIfAbsent()
是原子的。我的问题是ConcurrentHashMap中的方法put()
也是原子的?文档中没有明确说明put
或get
是原子的。然而,缔约国指出:
检索反映了最近完成的更新操作在开始时的结果。(更正式地说,给定键的更新操作与报告更新值的该键的任何(非null)检索具有“发生在前”关系。)
这意味着如果一个线程使用相同的键执行put
,另一个线程执行get
,那么get
将看到“在put之前”状态或“在put之后”状态。这实际上意味着,get
和put
相互之间是原子的,对于其他明确的原子操作。。。所有这些都适用于给定的密钥。事实上,如果不是这样的话,ConcurrentHashMap
就不是常规/直观意义上的线程安全
然而,javadocs并没有为涉及不同密钥的操作提供强有力的保证。因此原子性是有限的
这种原子性不是一个特别有趣或有用的性质。例如,虽然put
和get
分别是原子的,但是put
后跟get
不是原子的。很难看出您将如何利用这些操作的有限原子性。。。除了一般的线程安全之外
(依我看,这可能是他们不愿意在javadoc中明确提到get
和put
原子性的原因。)
更有趣的特性是更复杂操作的原子性(或非原子性)。例如,像
putIfAbsent
、compute
和merge
这样的操作是原子操作,但批量操作不是原子操作。文档中没有明确说明put
或get
是原子操作。然而,缔约国指出:
检索反映了最近完成的更新操作在开始时的结果。(更正式地说,给定键的更新操作与报告更新值的该键的任何(非null)检索具有“发生在前”关系。)
这意味着如果一个线程使用相同的键执行put
,另一个线程执行get
,那么get
将看到“在put之前”状态或“在put之后”状态。这实际上意味着,get
和put
相互之间是原子的,对于其他明确的原子操作。。。所有这些都适用于给定的密钥。事实上,如果不是这样的话,ConcurrentHashMap
就不是常规/直观意义上的线程安全
然而,javadocs并没有为涉及不同密钥的操作提供强有力的保证。因此原子性是有限的
这种原子性不是一个特别有趣或有用的性质。例如,虽然put
和get
分别是原子的,但是put
后跟get
不是原子的。很难看出您将如何利用这些操作的有限原子性。。。除了一般的线程安全之外
(依我看,这可能是他们不愿意在javadoc中明确提到get
和put
原子性的原因。)
更有趣的特性是更复杂操作的原子性(或非原子性)。例如,
putIfAbsent
、compute
和merge
等操作是原子操作,但批量操作不是原子操作。如果我负责此API,我会将其添加到文档中,但有一个解释:
put
本质上是一个单数操作。与中一样,put的定义(来自java.util.Map
的定义)是原子的
当然,仅仅因为某些方法任务是以原子方式描述的,并不意味着实现是原子的,而对于集合框架中的许多东西来说,它们不是原子的。ArrayList的add方法是原子描述,但不是原子实现
区别在于,添加作业的描述只是“将元素添加到末尾”。它不是“搜索结束节点,一旦找到,将此元素添加为它的尾部引用”。它不是“获取列表的大小并记住它”。然后,检查此列表的容量,如果它不足以向其中添加项目,请先按增长因子扩展容量,然后将先前获得的“大小”索引的值设置为传入的对象
尽管后一个冗长的描述或多或少正确地描述了ArrayList.add的实际功能
因此,ConcurrentHashMap
的javadoc在类级别和方法级别协同工作:
put()
本质上被描述为一个原子操作,而putIfAbsent
的描述根本不是原子操作。它被明确描述为一个两步过程;甚至在名字里放置,如果不存在-这是一个两步名称。因此,DOCS需要走出去说:即使听起来像两步操作,也可以认为它是原子的。
然后CHM的javadoc类说所有的原子操作实际上都是原子实现的
为了进行对比,类似于putAll
的内容被描述为一个多步骤过程,CHM文档没有明确说明putAll
是原子的。事实并非如此。您可以观察到您正在使用putAll
添加的内容中有一半已添加到单独的列表中(putAll的行为与<