Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ConcurrentHashMap更改对所有线程可见吗?_Java_Multithreading_Thread Safety_Volatile_Concurrenthashmap - Fatal编程技术网

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

Java ConcurrentHashMap更改对所有线程可见吗?,java,multithreading,thread-safety,volatile,concurrenthashmap,Java,Multithreading,Thread Safety,Volatile,Concurrenthashmap,我的CHM定义如下。每当有任何更新时,我都从一个后台线程调用setDataProcess方法。我总是从多个读卡器线程调用getDataMapping private static final ConcurrentHashMap<ProcessType, Mapping> mappingsHolder = new ConcurrentHashMap<ProcessType, Mapping>(); private static final CountDownLatch ha

我的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);
    }
}
private static final ConcurrentHashMap mappingsHolder=new ConcurrentHashMap();
private static final CountDownLatch hasInitialized=新的CountDownLatch(ProcessType.values().length);
公共静态void setDataProcess(ProcessType ProcessType,映射newMapData){
mappingsHolder.put(processType,newMapData);
hassinitialized.countDown();
}
公共静态映射getDataMapping(ProcessType ProcessType){
试一试{
hasInitialized.await();
返回mappingsHolder.get(processType);
}捕捉(中断异常e){
Thread.currentThread().interrupt();
抛出新的非法状态异常(e);
}
}

问题是-
mappingsHolder
CHM中的任何更改都将立即对所有读卡器线程可见,或者我需要使用volatile来实现这一点?

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


但是,像往常一样,还有一个潜在的计时问题:线程可能在您更改之前或之后读取一个值。基本上,
concurrentHashMap
不会因为一次被多个线程使用而被破坏。因此,这是一个必要的功能。但是,仅此一点并不能真正解决线程为了成功地协同工作而可能需要的任何其他同步或通知要求。

据我所知,您正在read方法中使用
countdownlock
等待计数达到零。计数显然是
ProcessType
中枚举常量的数量。如果正确实现了此
倒计时闩锁
,则不会出现问题,因为根据,应该存在“发生在”关系:

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

忽略倒计时闩锁因子,在检索密钥时不同步,而是检索与密钥对应的最新值

检索操作(包括
get
)通常不会阻塞,因此可能与更新操作(包括
put
remove
)重叠检索反映最近完成的更新操作在开始时的结果。


这意味着线程所做的更改对于读取密钥的线程是可见的。但是这两个线程可能会相互干扰。

倒计时闩锁确保倒计时之前的操作发生在另一个线程从wait返回之前,如图所示

至于ConcurrentHashMap,内容如下:

给定键的更新操作与报告更新值的该键的任何(非null)检索具有“发生在”关系


它应该处理映射更改的可见性,以使从中读取的线程可见。

尝试查看有多困难?@Alp:对于可见性问题,尝试并查看是不重要的。esp,因为如果失败,它可能位于不同的硬件上,具有比x86更宽松的规则。您是否使用了倒计时闩锁,以便只有在mappingsHolder被填充后才能调用getDataMapping?@adhg是的,您是对的。很酷。看起来在这种情况下,volatile是冗余的。CDL在启动期间是一次同步,但在启动之后必须是原子更新,这样所有线程都可以看到CHM更改?感谢您的编辑,这意味着它将是原子更新,所有线程都可以看到对CHM的任何更改,对吗?