volatile

volatile具备的两种特性:

  1、可见性

  2、禁止指令重排

解析:

  1、可见性:用volatile修饰的变量,会使线程在使用该变量时,每次都从主内存中读取到工作内存,再使用。

    对比普通的变量,线程在使用时,如果工作内存中没有该变量,则先从主内存中拷贝,在使用。如果工作内存中已经存在了该变量,则不再从主内存中重新读取。

  volatile变量,由于每次都从主内存中先同步,再使用。由此来保证可见性。

  2、禁止指令重排:用volatile修饰的变量,会使线程在使用变量的时候,禁止指令重排。

    对比普通的变量,线程在使用时,如果存在两处赋值,而这两处赋值对于后续的计算没有影响,那么可能由于优化的原因,而进行指令重拍。

  举例:单例模式(双检锁实现)

  public class Singleton{

    private static Singleton instance;//定义一个单例

    public static Singleton getInstance(){

      if ( instance == null ) {

         synchronized(Singleton.class){

            if( instance == null ){

              instance = new Singleton();

            }

         }      

      }

    }

    private Singleton(){} //私有构造方法

  }

  指令重排,在 instance = new Singleton();这一句中,有可能线程A还未完成全部的初始化工作,就已经将结果赋值给了instance这个变量。

  此时:线程B执行第一个if ( instance == null ) 判断,获取到对于的instance实例,在执行该实例对于的方法时,会由于实例未完成初始化工作,而导致异常。

因此:需要将instance变量,定义为volatile类型。

 

变量可见性的保证,还有另外两种方式:synchronized,final。

  synchronized:加锁后,一次只能有一个线程访问变量,而且每次放完变量后,需要unlock变量,变量才能被其它线程使用,因此能保证可见性。

  final:final的不变性,保证可见性。

 

synchronized 与 volatile 的区别是,volatile不保证原子性,所以不是线程安全的。

posted @ 2018-10-16 22:44  陈标  阅读(138)  评论(0)    收藏  举报