2011-05-13 38 views
6

我一直在阅读自昨天以来,我不知道很多事情......但有些事情开始变得清晰...
我明白为什么双重检查锁定不安全(我想知道什么是罕见的条件的可行性发生),但挥发性修复了1.5 +问题....
但我不知道这是否与putifAbsent为什么ConcurrentHashMap.putifAbsent是安全的?

像时...

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

然后做到这一点保证了myObj将是100%当另一个线程做了时,???因为它可以有完全的心不是初始化一个引用(双重检查锁定的问题)

回答

3

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

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

+0

所以,如果我理解正确没有问题,就像在经典的双重检查锁定范例? – GorillaApe 2011-05-13 20:36:18

+0

@Parhs:对,没有问题。 – ColinD 2011-05-13 20:45:32

+0

你是对的。你实际上在'你的问题中自己回答了'但是不稳定可以解决1中的问题。5 +'由于从CCHM返回的值是一个易失值,因此它也可以安全地进行部分初始化。 – 2011-05-13 20:45:47

1

我不是这方面的专家,但在ConcurrentHashMap望着Segment实施我看到volatilecount似乎被用来确保线程之间的正确可见性所有读取操作必须读取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. 
2

putIfAbsentConcurrentHashMap中的方法是check-if-absent-then-set方法。这是一个原子操作。但要回答以下部分:“那么这是否确保当另一个线程执行cHashM.get()时myObj将100%真空”,这取决于对象何时放入HashMap。通常在发生优先事件之前有一个发生 - 即,如果调用者在将对象放置在地图中之前获得第一个,则将返回null,否则将返回该值。

+0

返回null不会是一个prb,但是对非完全构造的初始化对象的引用将是。 (双重检查锁定的问题) – GorillaApe 2011-05-13 20:38:02

2

文档的相关部分是这样的:

内存一致性效果:与 其他并发集合,在一个线程动作 将物体放置 成的ConcurrentMap键或值 之前发生 - 在 之后的动作之前,从另一个 线程中的ConcurrentMap访问或删除该对象 。

- java.util.ConcurrentMap

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