同步方法或同步块:在java中编写单例类时哪一个更好?

时间:2017-12-26 12:43:53

标签: java multithreading singleton

正如我们在创建单例类时所知道的同步操作一样,我们将整个方法设置为同步或仅将负责创建对象的语句块作为synchronized.But,这两种方法中哪一个更好,为什么?

方法1

public static A getA(){  
    if (obj == null){  
        synchronized(Singleton.class) {
            if (obj == null) {
                obj = new Singleton();//instance will be created at request time  
            }  
        }   
    }  
    return obj;  
} 

方法2

public synchronized static A getA(){  
    if (obj == null){  
        obj = new Singleton();//instance will be created at request time  
    }   
    return obj;  
} 

4 个答案:

答案 0 :(得分:1)

第一个更好,因为当obj不为空时你没有获得锁定,而第二个方法每次都获得锁定。

答案 1 :(得分:1)

<强>概念

public synchronized static A getA(){  
    if (obj == null){  
        obj = new Singleton();//instance will be created at request time  
    }   
    return obj;  
} 

在方法上使用synchronization关键字(如上例所示)同步对整个方法的访问,这通常是非常安全的,但除非你有一个非常小的方法,否则你可能正在同步一大块代码而不是你绝对需要的to,这更像是一个不必要的性能。因为同步块/方法一次只能由一个线程访问,所以它们确实会降低处理速度。您同步的代码块越大,性能就越差。

如果您只需要一个延迟加载的资源,则需要执行以下操作:

class MyClass {
      private static volatile Resource resource;
      private static final Object LOCK = new Object();

      public static Resource getInstance() {
            if(resource == null) { 
                synchronized(LOCK) { // Add a synch block
                    if(resource == null) { // verify some other synch block didn't
                                           // write a resource yet...
                        resource = new Resource();
                    }
                }
            }
            return resource;
      }
 }

这里的一个重要事项是volatile修饰符,为您应用中的整个主题提供可见性。

答案 2 :(得分:1)

我会选择第一个,它具有双重检查锁定。

也许你也可以尝试这样的事情:

public class MySingleton {
       private static instance = new MySingleton ();
       private MySingleton (){ }
       public MySingleton getInstance {
            return instance;
       }
 }

答案 3 :(得分:1)

你最好使用Holder idiom

inWhichArea = function(map, loc) {
  for (var i in feats) {
    var area = feats[i].getGeometry();
    var poly = new google.maps.Polygon({
      paths: area.getAt(0).getArray(),
      map: map,
      clickable: false
    });
    if (google.maps.geometry.poly.containsLocation(loc, poly)) {
      return feats[i];
    }
  }
  return null;
}

它是懒惰的,因为实例将在第一次调用public class HolderFactory { public static Singleton get() { return Holder.instance; } private static class Holder { public static final Singleton instance = new Singleton(); } } 时创建,并且它是线程安全的,因为类保证由类加载器在单个线程中加载。 您还可以查看此链接,了解有关单身人士和线程安全的更多详细信息:https://shipilev.net/blog/2014/safe-public-construction/