您可以确保一个线程对变量所做的更改可以在其他线程上看到,方法是使变量变为 volatile,或者让两个线程在某事上同步。如果要更改的是 java.util.ConcurrentHashMap,通过将保存此映射的变量的类型声明为 volatile 来创建内存屏障是否有意义,或者访问映射的读者(例如 via myMap.values()
)将获得最新的无论如何可能的观点?对于上下文,我有一个繁重的阅读,轻的写作场景,我正在将我的无锁读取解决方案切换到 ConcurrentHashMap。
4 回答
ConcurrentHashMap 保证写入和后续读取之间存在先发生关系。所以是的,当您阅读 (get) 时,您将看到已“提交”的最新更改(put 已返回)。
注意:这不适用于 javadoc 中解释的迭代器。
“持有”映射的变量是映射对象的引用或指针(分别(简化)到存储映射的内存地址)。使其 volatile 只会影响指针,而不影响地图对象本身。只要您始终使用相同的 Map-Object 并确保映射在线程使用它之前已完全初始化,您就不必对它使用“易失性引用”。并发在并发哈希映射中透明地处理。
是的,ConcurrentHashMap
给出了最新的观点。如果您参考http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html#get(java.lang.Object)上的 javadocs,
它清楚地写着
检索反映了最近完成的更新操作在开始时保持的结果
它有更多细节,我建议你去阅读它。
此外,正如已经指出的那样,使用volatile
不是您想要的,因为它只会影响指针而不是地图的实际内容。
您需要做的就是确保保存地图的引用是最终的,这样您就会获得一个最终的字段围栏,以确保您看到正确初始化的地图并且引用本身不会更改。
正如其他人指出的那样,ConcurrentHashMap
将保证内部写入的可见性/发生之前,就像所有java.util.concurrent.*
集合一样。但是,您应该使用ConcurrentMap
接口上公开的条件写入来避免写入中的数据竞争。