码迷,mamicode.com
首页 > 其他好文 > 详细

4、volatile关键字

时间:2015-06-02 15:05:30      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:

关键字volatile可以说是Java虚拟机提供的最轻量级的同步机制。当一个变量定义为volatile之后,它将具备两种特性,第一是保证此变量对所有线程的可见性,这里的“可见性”是指当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的。而普通变量不能做到这一点,普通变量的值在线程间传递需要通过主内存来完成,例如,线程A修改一个普通变量的值,然后向主内存进行回写,另外一条线程B在线程A回写完成之后再从主内存进行读取操作,新变量值才会对线程B可见。

 

然我们来看看一个有名的“双重检测锁单例模式”的实现:

 1 private static Singleton _instance;
 2 public static Singleton getInstance() {
 3    if(_instance==null) {                 //第一重检测
 4      synchronized(Singleton.class) {
 5         if(_instance==null) {            //第二重检测
 6            _instance=new Singleton();
 7         }
 8      }
 9    }
10    
11    return _instance;
12 }

两个问题:

一、为什么需要双重检测?

如果我们就是用一重检测加上同步代码块,当然能达到我们想要的效果,但是性能严重降低。因为我们仅仅只是需要在第一次请求才需要加锁,而后我们只需要将实例返回即可。

 

二、上面的程序是否存在问题?

当然存在问题。假设现在我们有4个线程(A、B、C、D)第一次都通过了第一层检测,当一个线程A进入到同步代码块后,对普通变量_instance进行写操作,但是这个写操作对于线程B、C、D有可能是不可见的。因为当B、C、D进行第二重检测时,也就是B、C、D要去主内存当中读取普通变量,但是这时候A线程在工作内存当中对_instance变量的修改,不一定就更新到了主内存当中。

 

为了使得线程A对_instance的写对B、C、D线程的读可见,那么变量_instance需要加上volatile关键字。因为JVM确保了volatile关键字修改的变量的写操作先行于(happen-before)后面的读操作。换一句话说,就是之前的写操作都能反应到读操作当中。但是如果在读了之后,再次被别的线程发生了写操作,然后该线程再将其写回主内存,就会导致数据不一致,因此volatile并不是线程安全的。

4、volatile关键字

标签:

原文地址:http://www.cnblogs.com/feijishuo/p/4546321.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!