将ConcurrentHashMap安全发布到类字段中

问题描述 投票:3回答:1

我正在尝试编写一个测试,以证明在多线程环境中为类的字段分配新的引用不是线程安全的,更具体地说,如果该字段未声明为volatile或[ C0]。

我使用的场景是AtomicReference类(如下所示),它应该加载存储在PropertiesLoader中的一组属性(当前仅使用一个属性),并且还尝试支持重新加载。因此,有许多线程正在读取属性,并且在某个时间点,另一个线程正在重新加载需要对读取线程可见的新值。

该测试旨在按以下方式工作:

  • 它调用正在旋转等待的读取器线程,直到它们“看到”属性值更改
  • 编写器线程有时会使用该属性的新值创建一个新映射,并将该映射分配给所讨论的字段(Map<String, String>
  • 如果所有阅读器线程都看到新值,则测试完成,否则将永远挂起。

现在我知道严格来说,没有测试可以证明一些代码的线程安全性(或缺少代码),但是在这种情况下,我觉得证明该问题相对容易至少根据经验。

我尝试使用PropertyLoader.propertiesMap实现来存储属性,在这种情况下,即使我仅使用一个读取线程,测试也会按预期挂起。

但是,如果使用HashMap实现,则无论使用多少读取线程,测试都不会挂起(我也尝试在读取器线程中随机等待,但没有成功。)>

据我所知,ConcurrentHashMap是线程安全的这一事实不应影响对其分配到的字段的可见性。因此,该字段仍需要ConcurrentHashMap / volatile。但是,上述测试似乎与此矛盾,因为它的行为就像始终安全地发布地图一样,而无需其他同步。

我的理解错误吗?也许AtomicReference做出了一些其他我不知道的同步承诺?

任何帮助将不胜感激。

P.S。下面的代码应该可以作为Junit测试执行。我已经在装有AMD Ryzen 5,Windows 10,JDK 1.8.0_201的计算机上运行了它,并在另一台装有i7英特尔的Fedora 30,JDK 1.8.xx(不记得JDK的确切版本)的计算机上运行了相同的结果。

ConcurrentHashMap

我正在尝试编写一个测试,以证明在多线程环境中为类的字段分配新的引用不是线程安全的,如果存在该问题,更具体地说是具有可见性问题...

java multithreading thread-safety safe-publication
1个回答
0
投票
比您想象的要差一些,但也有节省的余地。
© www.soinside.com 2019 - 2024. All rights reserved.