论坛首页 Java企业应用论坛

关于单例模式的两种模式懒汉式和饿汉式的线程安全问题

浏览 3898 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (3)
作者 正文
   发表时间:2012-03-22  
//两种单例模式 关于线程安全的问题




//饿汉式   是线程安全的*/
class  Single
{
private static  final Single s = new Single();
private Single(){

}
public static Single getInstance(){
  return s;
}
}

//懒汉式   有线程安全问题
//懒汉式可以实现延迟加载
//但是在多线程并发访问的情况下会出现安全问题
//可以通过加同步来解决,只是加上同步效率会稍低,这时候可以再使用双重判断来解决这个低效的问题
//加同步的时候使用的锁是 该类所属的字节码文件对象


class Single
{
private static Single s = null;
private Single(){

}
public static Single getInstance(){
  if(s == null){
   synchronized(Single.class){
    if(s == null){
     s = new Single();
    }
   }
  }
  return s;
}
}
   发表时间:2012-03-22   最后修改:2012-03-22
这几天单例肿么这么火?


前面的s并没有声明为volatile
那么,现有两个线程同时调用getInstance,a先判断为null,于是去new了一个,问题在于赋值给instance之后,b线程不一定能见到这个值,b判断s==null的时候可能还是true,于是又去new了一个

另外,s=new Single();是分为好几步操作的:
0:   new     #2; //Single
1:   dup
2:   invokespecial   #3; //Method Single."<init>":()V
3:   astore_1

在非volatile情况下,有没有可能被reorder成下面这样呢:
0:   new     #2; //SingltonThread
1:   dup
3:   astore_1
2:   invokespecial   #3; //Method Single."<init>":()V

即,内存已经分配了,还没有调用构造函数,但s已经被赋值了,也不一定对其他线程可见,如果可见,第二个线程立马就拿s去用,这时候s实例尚未完全构建好,使用的时候是否可能会出问题呢

jdk1.4及之前,不能保证volatile变量不参与reorder,所以,1.4下双重加锁检查仍有问题
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics