使用以下两个版本的Singleton Classes之间有什么区别
在第一个我使用的是synchronized(Singleton.class)
在第二个我使用的是同步(Obj) //第一类 公共类Singleton {
private static Singleton obj = null;
Singleton() {
}
public static Singleton getInstance() {
synchronized(Singleton.class){
if (obj == null) {
obj = new Singleton();
}
}
return obj;
}
}
//第二种类型
public class Singleton {
private static Singleton obj = null;
Singleton() {
}
public static Singleton getInstance() {
synchronized(obj){
if (obj == null) {
obj = new Singleton();
}
}
return obj;
}
}
答案 0 :(得分:2)
主要区别在于synchronized(obj)
不起作用:第一次调用它时,obj
为null
,因此您将看到NullPointerException
}。
Singleton.class
永远不会null
,因此您可以将其用于同步。但是,恶意代码可以执行攻击,使您的getInstance
方法永远等待:他们只需锁定您的Singleton.class
,并在那里等待无限。
针对此攻击的常见防御是为您的锁使用单独的私有静态对象,如下所示:
public class Singleton {
private static Singleton obj = null;
private static final Object syncRoot = new Object();
Singleton() {
}
public static Singleton getInstance() {
synchronized(syncRoot){
if (obj == null) {
obj = new Singleton();
}
}
return obj;
}
}
答案 1 :(得分:1)
第二个版本尝试在null
上进行同步,这将失败。 synchronized
关键字尝试获取Object
引用的obj
上的锁定,因为它最初为null
,您将获得NulPointerException
。< / p>
答案 2 :(得分:1)
它们实际上是相同的,也是一个糟糕的实现,因为obj IS NULL(在你的例子中)和代码单线程每次调用它。它应该使用双重检查锁...
第二个应该是:
public class Singleton {
private static object syncRoot = new object();
private static Singleton obj = null
Singleton() {
}
public static Singleton getInstance() {
if ( obj == null ){
//ONLY SINGLE THREAD IF obj == null
synchronized(syncRoot){
if ( obj == null ){
obj = new Singleton();
}
}
}
return obj;
}
}
答案 3 :(得分:0)
当你使用synchronized(Singleton.class)时,同步只会在第一次创建实例时应用,并且当我们有一个可能通过我们的代码运行多个线程的场景时使用它。你的if循环将负责在没有可用的情况下创建另一个实例,通过使用这种同步方式,我们减少了大量的开销,因为我们知道同步类在时间/等待方面增加了很多。