理解volatile特性的一个好方法是吧对volatile变量的单个读/写,看成是使用同一个锁对这些单个读/写操作做了同步。
1 class VolatileFeatureExample{ 2 volatile long vl = 0L; 3 public void set(long L){ 4 vl = L; 5 } 6 public void getIncrement(){ 7 vl++; 8 } 9 public long get(){ 10 return vl; 11 } 12 } 13 //等价于 14 class VolatileFeatureExample{ 15 long vl = 0L; 16 public synchronized void set(long L){ 17 vl = L; 18 } 19 public void getIncrement(){ 20 long temp = get(); 21 temp += 1L; 22 set(temp); 23 } 24 public synchronized long get(){ 25 return vl; 26 } 27 }
即使是64位的long型和double型变量,只要它是volatile变量,对这些变量的读/写就具有原子性。
如果是多个volatile操作或类似于volatile++这种复合操作,这些操作整体上不具有原子性。
volatile 写的内存语义:当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存中。
volatile读的内存语义:当写一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。
编译器不会对volatile读与volatile读后面的任意内存操作重排序。
编译器不会对volatile写与volatile写前面的任意内存操作重排序。
volatile变量的读/写和CAS可以实现线程间的通信。