我试图找到自己的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;
}
此代码有效吗? 如果不行,怎么解决?
答案 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;
}
}