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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了同步方法或同步块:在java中编写单例类时哪一个更好? [重复]相关的知识,希望对你有一定的参考价值。

这个问题在这里已有答案:

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

方法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;  
} 
答案

概念:

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

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

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

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修饰符,为应用程序中的整个线程提供可见性。

另一答案

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

另一答案

我会采取第一个,具有双重检查锁定。

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

public class MySingleton {
       private static instance = new MySingleton ();
       private MySingleton (){ }
       public MySingleton getInstance {
            return instance;
       }
 }
另一答案

你最好使用Holder成语

public class HolderFactory {
   public static Singleton get() {
      return Holder.instance;
   }

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

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

以上是关于同步方法或同步块:在java中编写单例类时哪一个更好? [重复]的主要内容,如果未能解决你的问题,请参考以下文章

为啥将 volatile 与同步块一起使用?

关于单例模式这种比上面12都好一些,既实现了线程安全,又避免了同步带来的性能影响。

synchronized同步块和volatile同步变量

适当使用同步或锁定一段代码

单例模式(Singleton)

同步方法同步代码块volidate变量的使用