使用java.util.concurrent.Concurrent*容器时使用volatile有什么用?

Ble*_*dof 3 java concurrency volatile

当我看到这段代码时,问题出现了:

private static volatile ConcurrentHashMap<String, String> cMap = null;
static {
    cMap = new ConcurrentHashMap<String, String>();
}
Run Code Online (Sandbox Code Playgroud)

对我来说,看起来像volatile是冗余的,因为容器是ConcurrentHashMap,根据JavaDoc已经同步了puts,DUH,使用cMap的类只实例化它一次并且没有任何设置或获取它的方法.

我在这里看到的唯一提供volatile的是,如果我将cMap设置为在不久的将来引用一个新对象,那么这些读取和写入将被同步.

我错过了什么吗?

Jon*_*eet 7

volatile修改并没有什么做与所涉及的类-它只是用做变量 cMap.它只影响线程获取或更改该变量值的方式.当你在引用的对象上调用方法时,你已经超越了bailiwick volatile.

正如您所说,它基本上确保所有线程都能保证看到cMap值的更改(即使其引用不同的映射).

可能是一个好主意 - 或者可能不是,这取决于代码的其余部分.如果你可以做到这一点final,你就不需要它volatile......


irr*_*ble 5

除非稍后重新分配变量,否则完全不需要volatile.

静态初始化程序中发生的任何写入对于使用该类的任何代码都是可见的(即,当访问静态方法/字段时,调用构造函数时)

没有这种保证,我们陷入了深深的麻烦.数百万行代码是错误的.

见JLS3 $ 12.4.2:

初始化类或接口的过程如下:

  1. 在Class对象上同步(第14.19节),该对象表示要初始化的类或接口.