ConcurrentHashMap更改对所有线程可见吗?

时间:2015-07-03 17:56:44

标签: java multithreading thread-safety volatile concurrenthashmap

我的CHM定义如下。每当有任何更新时,我都会从单个后台线程调用setDataProcess方法。我总是从多个读者线程中调用getDataMapping

private static final ConcurrentHashMap<ProcessType, Mapping> mappingsHolder = new ConcurrentHashMap<ProcessType, Mapping>();
private static final CountDownLatch hasInitialized = new CountDownLatch(ProcessType.values().length);

public static void setDataProcess(ProcessType processType, Mapping newMapData) {
    mappingsHolder.put(processType, newMapData);
    hasInitialized.countDown();
}

public static Mapping getDataMapping(ProcessType processType) {
    try {
        hasInitialized.await();
        return mappingsHolder.get(processType);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new IllegalStateException(e);
    }
}

问题是 - mappingsHolder CHM中的任何更改都会立即显示给所有读者线程,或者我需要使用volatile吗?

3 个答案:

答案 0 :(得分:4)

据我所知,您在read方法中使用CountDownLatch等待计数达到零。计数显然是ProcessType中的枚举常量数。如果CountDownLatch已正确实施,那么问题不应该是问题,因为根据javadocs,应该有一个先发生过的关系:

  

内存一致性影响:在计数达到零之前,在调用countDown() 之前的某个线程中的操作发生在之后的操作发生之后,从另一个中的相应await()成功返回线程。

忽略CountDownLatch因素,ConcurrentHashMap在检索密钥时不会同步,但会检索与密钥对应的最新值。

  

检索操作(包括get)通常不会阻止,因此可能与更新操作重叠(包括putremove)。 检索反映了最近已完成更新操作的结果。

这意味着线程所做的更改对于读取键的线程是可见的。但这两个人可以干涉。

答案 1 :(得分:2)

CountdownLatch确保在countDown之前的操作发生 - 在另一个线程从等待返回之前,Manouti said

对于ConcurrentHashMap,the api documentation读取:

  

给定密钥的更新操作与报告更新值的该密钥的任何(非空)检索具有先发生关系。

应该可以处理对从中读取的线程的地图更改的可见性。

答案 2 :(得分:0)

由于变量的值(即地图内存中的位置)不会改变,所以我怀疑volatile会在这里产生影响。地图对象一旦分配,就不会四处移动。

但是,一如既往存在潜在的时间问题:线程可以在您更改之前或之后读取值。基本上,concurrentHashMap不会被销毁一次被多个线程使用。因此,这是一个必要的功能。但是,仅凭这一点并未真正解决线程可能需要的任何其他同步或通知要求才能成功协同工作。