技术开发 频道

Java中的模式--单态

  三,为了解决上边的问题:单态模式3,加入同步。

  public static Singleton getInstance()
  {
  
if (instance == null)
  {
  
synchronized(Singleton.class) {
  instance
= new Singleton();
  }
  }
  
return instance;
  }

   同步改成块同步,而不使用函数同步,但是仔细分析,又回到了模式一的状态,再多线程的时候根本没有解决问题。

  四,为了对应上边的问题:单态模式4,也就是很多人采用的Double-checked locking。

  public static Singleton getInstance()
  {
  
if (instance == null)
  {
  
synchronized(Singleton.class) { //1
  
if (instance == null) //2
  instance
= new Singleton(); //3
  }
  }
  
return instance;
  }

  这样,模式一中提到的问题解决了,不会出现多次实例化的现象。

  当第一次进入的时候,保正实例化时候的单态,在实例化后,多线程访问的时候直接返回,不须要进入同步模块,既实现了单态,又没有损失性能。表面上看我们的问题解决了,但是再仔细分析:

  我们来假象这中情况:

  Thread 1 :进入到//3位置,执行new Singleton(),但是在构造函数刚刚开始的时候被Thread2抢占cpu
  Thread 2 :进入getInstance(),判断instance不等于null,返回instance,(instance已经被new,已经分配了内存空间,但是没有初始化数据)
  Thread
2 :利用返回的instance做某些操做,失败或者异常
  Thread
1 :取得cpu初始化完成

  过程中可能有多个线程取到了没有完成的实例,并用这个实例作出某些操做。

  出现以上的问题是因为:

  mem = allocate(); //分配内存
  instance = mem; //标记instance非空
  
//未执行构造函数,thread 2从这里进入
  ctorSingleton(instance); //执行构造函数
  
//返回instance
0
相关文章