volatile关键字理解
volatile是一个轻量级的同步机制,相比传统的锁(如synchronized),在性能上面是有优势的,但是虚拟机对锁有过优化,所以很难确切的说volatile比synchronize快上多少。
volatile三大特性
- 保证可见性
- 防止指令重排
- 不保证原子性
一、保证可见性
Java内存模型(JMM)规定了所有的变量都存储在主内存中,每个线程都在自己的工作内存中维护着变量的副本,对变量的所有操作都是在工作内存中进行的,不同的线程之间无法访问对方工作内存中的变量,线程之间变量值的传递都需要通过主内存来完成。
当一个变量被定义为volatile后,一个线程修改了变量值后,其他线程会立即得知(原理:当主内存中的变量被修改后,会通知其他线程将自己工作内存中的该变量副本设置为无效,如果在使用到这个变量时,发现是无效状态,就会从主内存中重新读取),所以这就是所谓的“可见性”。
二、防止指令重排
Java中会存在指令重排优化,这是我们无法感知到的,但是在多线程情况下,指令重排可能会导致问题或者资源浪费,所以使用volatile关键字可以防止指令重排,举一个简单的单例实现:
1 // 定义volatile变量,防止指令重排,对象实例化的过程并不是原子性的,所以存在Java编译器指令重排优化可能 2 // 对象实例化过程:1.分配内存空间 2.初始化对象 3.将对象的引用指向分配的内存 3 // 如果不加volatile,因为存在指令重排的可能,就可能存在其他线程拿到未初始化完成的对象,从而导致线程不安全 4 private volatile static Singleton instance; 5 6 public Singleton getInstance() { 7 // 多线程情况下,防止重复实例化,浪费资源和效率 8 if (instance == null) { 9 // 加锁进行控制,防止多线程情况下重复实例化 10 synchronized (Singleton.class) { 11 // 多线程情况下,获取到锁后也再判断一下,如果其他线程已经实例化,也就无需再次实例化,还是防止重复实例化 12 if (instance == null) { 13 instance = new Singleton(); 14 } 15 } 16 } 17 return instance; 18 }
三、不保证原子性
对于非原子性操作,如i++,会存在问题,可以使用atomic包下的相关类来保证原子性
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号