单例实现示例

时间:2013-05-10 13:39:19

标签: java design-patterns singleton

我试图找到自己的Java Singleton实现方式。 代码如下:

public class Singleton{
   private volatile static Singleton _instance = null;
   private Singleton(){}
   public static Singleton getInstance(){
      if (_instance == null)
         Object obj = new Object();
         synchronized(obj){
            if (_instance == null)
               _instance = new Singleton();
         }
      return _instance;
}

此代码有效吗? 如果不行,怎么解决?

5 个答案:

答案 0 :(得分:3)

不 - 你的代码不起作用,因为lock对象是一个局部变量,因此每个线程都不同。

您正在尝试实施lazy initialization模式 - 首次使用时创建实例。

但是有一个简单的技巧可以让你编写需要同步的线程安全实现!它被称为Initialization-on-demand holder idiom,它看起来像这样:

public class Singleton {
    private static class Holder {
        static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }

    private Singleton() {
    }

    // rest of class omitted
}

此代码在第一次调用getInstance()时初始化实例,并且由于类加载器的契约,重要的是不需要同步:

  • 类加载器在首次访问时加载类(在这种情况下Holder只能访问getInstance()方法)
  • 当一个类被加载时,在任何人都可以使用它之前,所有的静态初始化器都保证被执行(那就是当Holder的静态块被激活时)
  • 类加载器内置了自己的同步,使上述两点保证为线程安全

这是我在需要延迟初始化时使用的一个巧妙的小技巧。您还可以获得final实例的奖励,甚至认为它是懒惰创建的。还要注意代码的清晰和简单。

答案 1 :(得分:2)

非懒惰单身人士的嘀嗒和非常简单的实施:

public enum TickySingleton {

    INSTANCE;

    public void doSomething() { ... }
    public Object returnSomething() { ... }
}

}

不是每个人都会喜欢这个。 ;)

答案 2 :(得分:1)

如果您的同步对象是final static,那会更好。否则,每个可能的并发线程将创建自己的同步对象并锁定不同的对象。他们不会等彼此。

public class Singleton{

   private final static Object obj = new Object();
   private volatile static Singleton _instance = null;

   private Singleton(){}

   public static Singleton getInstance(){
     if (_instance == null)
        synchronized(obj){
           if (_instance == null)
              _instance = new Singleton();
         }
      }
      return _instance;
   }

答案 3 :(得分:1)

当你写:

Object obj = new Object();
synchronized(obj){}

JVM可以证明没有两个线程可以获取该锁(因为它是一个局部变量),因此可以完全删除同步。

关于单身人士的一些评论:

答案 4 :(得分:0)

不,这不正确,你应该在Singleton.class上同步

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

这是一种已知的双重检查锁定模式,有关详细信息,请参阅http://www.ibm.com/developerworks/java/library/j-dcl/index.html

请注意,由于此类中只有一种方法,因此在没有任何双重检查技巧的情况下,它具有相同的用途,并且它也很懒惰

class Singleton {
       private static Singleton _instance = new Singleton();
       private Singleton(){}
       public static Singleton getInstance(){
          return _instance;
    }
}