并发情况下的单例安全问题

常见单例模式:饿汉式  懒汉式

饿汉式

public class Singleton1 {
  private Singleton1(){};
  private static final Singleton1 s = new Singleton1();
  public static synchronized Singleton1 getS(){
    return s;
  }
}

这种方式在类加载时就创建了一个实例对象, 避免了多线程的同步问题,获取对象的速度快, 但是启动过程比较消耗资源

另:构造函数 成员变量修饰符采用的都是private 即:在当前类中有效,为了避免在其他类中有new Singleton()的行为.

懒汉式

public class Singleton {

private static Singleton s;

private Singleton(){};
  public static Singleton gets(){
    if(s==null){
    s=new Singleton();
    }
    return s;
  }

}

懒汉模式申明了一个静态对象,在用户第一次调用时进行实例化创建,后续调用返回第一次创建的对象,但是它的线程是不安全的,多线程并发请求下可能出现创建多个对象的情况.

为了保证线程安全 通常情况下是加锁

public class Singleton {
private static Singleton s;
private Singleton(){};
  public static synchronized Singleton gets(){
    if(s==null){
      s=new Singleton();
    }
    return s;
    }

}

这种情况下 虽然保证了线程的安全,但是除第一次创建对象外,其他线程为判断对象是否为空就需要频换获取释放锁对象,锁的开销很大

锁下移,并保证第一次并发请求创建时的 安全问题

public class Singleton {
  private static Singleton s;
  private static String abc;
  private Singleton(){};
    public static Singleton gets(){
    if(s==null){
    //线程A 线程B 同时执行到这一步
    synchronized(abc){
      //A执行完,B进行创建前,再次判断对象是否创建,避免创建两个对象
      if(s==null){
        s=new Singleton();
        }
      }
    }
  return s;
}

}

 

posted @ 2018-11-14 10:21  烟火半边  阅读(315)  评论(0编辑  收藏  举报