为什么ConcurrentHashMap.putifAbsent是安全的?

时间:2011-05-13 20:13:08

标签: java concurrency concurrenthashmap

我从昨天起就一直在读书,我不知道很多事情......但是有些事情已经开始变得清晰了...... 我理解为什么双重检查锁定是不安全的(我想知道罕见情况发生的可行性是什么)但是挥发性修复了1.5 + ....的问题 但我想知道这是否与putifAbsent

一起发生

像...

myObj = new myObject("CodeMonkey");
cHashM.putIfAbsent("keyy",myObj);  

然后,当另一个线程执行myObj时,这是否确保cHashM.get()将被100%抗拒?因为它可能有一个引用未完全初始化(双重检查锁定问题)

4 个答案:

答案 0 :(得分:4)

如果调用concurrentHashMap.get(key)并返回一个对象,则保证该对象完全初始化。每个put(或putIfAbsent)将获取一个特定于桶的锁,并将该元素附加到存储桶的条目。

现在您可以浏览代码并注意到get方法不会获得相同的锁。所以你可以争辩说可能有一个过时的读物,这也不是真的。这里的原因是条目本身的值是不稳定的。所以你一定会得到最新的读物。

答案 1 :(得分:3)

putIfAbsent中的

ConcurrentHashMap方法是check-if-absent-then-set方法。这是一个原子操作。但是要回答以下部分:“那么这确保了当另一个线程执行cHashM.get()时,myObj将被100%初始化,它将取决于何时将对象放入HashMap。通常会有一个优先发生的优先级,即如果调用者在将对象放入映射之前获得第一个,那么将返回null,否则将返回该值。

答案 2 :(得分:2)

文档的相关部分是:

  

记忆一致性效果:与。一样   其他并发集合,操作   在放置对象之前的线程中   将ConcurrentMap作为键或值   发生在之后的行动之前   访问或删除该对象   来自ConcurrentMap的另一个   线程。

- java.util.ConcurrentMap

所以,是的,你有发生在之前的关系。

答案 3 :(得分:1)

我不是这方面的专家,但在[{1}}中查看Segment的实施情况我发现ConcurrentHashMap字段volatile似乎用于确保线程间的适当可见性。所有读操作都必须读取count字段,并且所有写操作都必须写入它。从课堂上的评论:

Read operations can thus proceed without locking, but rely
on selected uses of volatiles to ensure that completed
write operations performed by other threads are
noticed. For most purposes, the "count" field, tracking the
number of elements, serves as that volatile variable
ensuring visibility.  This is convenient because this field
needs to be read in many read operations anyway:

   - All (unsynchronized) read operations must first read the
     "count" field, and should not look at table entries if
     it is 0.

   - All (synchronized) write operations should write to
     the "count" field after structurally changing any bin.
     The operations must not take any action that could even
     momentarily cause a concurrent read operation to see
     inconsistent data. This is made easier by the nature of
     the read operations in Map. For example, no operation
     can reveal that the table has grown but the threshold
     has not yet been updated, so there are no atomicity
     requirements for this with respect to reads.