1. The "volatile" keyword ensures the visibility of variable value modifications.
For this point, we need to understand what variable values are in Java. For primitive type variables, the variable value is the assigned numerical value, for example, int a=1, where 1 is the variable value of the primitive type variable a. For reference type variables, the variable value is the address in the heap stack, for example, Object a=new Object(), where 0x11111111 is the variable value of variable a.
In summary, for primitive type variables, assigning a new value to them modifies their variable value, for example, a=2; while for reference type variables, modifying their address modifies their variable value, for example, a=new Object().
2. Array types ensure the visibility of internal elements.
In the case of volatile int[] a = new int[4], each element a[0], a[1], a[2], and a[3] in the array actually has visibility, and the determination of their visibility can refer to the first point (because each element in the array can be seen as a variable).
3. The visibility of a newly assigned variable cannot be ensured by a volatile variable.
volatile Object a = new Object();
Object b = a;
In this case, volatile cannot ensure the visibility of variable b.
In ConcurrentHashMap and CopyOnWriteArrayList, we can see the difference:
CopyOnWriteArrayList:
[Image]
[Image]
[Image]
We can see that in the first image, a is actually the array itself, so it has visibility, and we can safely retrieve the value using a[index].
ConcurrentHashMap:
[Image]
[Image]
[Image]
In the second image, we can see that table is assigned to a new variable tab. Although table itself is volatile, the new variable tab does not have visibility, so we need to use getObjectVolatile from Unsafe to safely retrieve the value.