有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

同步(Singleton.class)和同步(obj)之间的java差异

使用以下两个版本的单例类之间有什么区别

首先,我使用的是synchronized(Singleton.class)

在第二次使用同步(Obj) //第一类 公营单身人士{

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;
}
}

共 (4) 个答案

  1. # 1 楼答案

    第二个版本尝试在null上同步,但将失败。synchronized关键字尝试获取由obj引用的Object上的锁,由于它最初是null,您将得到一个NulPointerException

  2. # 2 楼答案

    它们实际上是相同的,而且是一个糟糕的实现,因为obj为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. # 3 楼答案

    当您使用synchronized(Singleton.class)时,只有在第一次创建实例之前才会应用同步,当我们有可能在代码中运行多个线程时才会使用同步。如果已经有一个实例可用,您的if循环将负责不创建另一个实例,通过使用这种同步方式,我们减少了大量的开销,因为我们知道同步类在时间/等待方面会增加开销

  4. # 4 楼答案

    主要的区别是synchronized(obj)不起作用:第一次调用它时,objnull,所以你会看到一个NullPointerException

    Demo on ideone.

    另一方面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;
        }
    }