关于java中volatile可见性适用范围的一些个人见解

1、volatile 保证了变量值修改的可见性

对于这一点，我们需要了解到在 java 中什么是变量值。对于基本类型变量，变量值就是赋予它的数值，比如 int a=1，那么 1 就是基本类型变量 a 的变量值。而对于引用变量类型，变量值就是堆栈中的地址，比如 Object a=new Object ()，那么 0x11111111 就是变量 a 的变量值。
综上所述，对于基本类型变量，我们为其赋新的值就是修改了其变量值，比如 a=2；而对于引用变量类型，我们修改了其地址就是修改了其变量值，比如 a=new Object ()。

2、数组类型保证内部元素的可见性

volatile int [] a = new int [4] 其实数组中的各个元素 a [0],a [1],a [2] 以及 a [3] 都具备可见性，而对于其可见性的判断，可以参考第一条（因为数组中的每一个元素都可以看作是一个变量）。

3、volatile 变量赋值的新变量无法保证可见性

volatile Object a = new Object();
Object b = a;
其中 volatile 无法保证变量 b 的可见性。
在 concurrentHashMap 和 CopyOnWriteArrayList 中我们可以看到不同：
CopyOnWriteArrayList：

可以看到第一张图中的 a 其实就是 array 本身，因此具备可见性，直接使用 a [index] 可以安全的获取值。

concurrentHashMap：

其中我们通过第二张图可以看到 table 被赋值给了一个新的变量 tab，尽管 table 本身被 volatile 修饰，但是新变量 tab 不具备可见性，因此需要使用 Unsafe 中的 getObjectVolatile 来安全地获取值。