如何在java中同步静态方法

在Java中实现单例模式时,我想出了这个问题。 即使下面列出的示例不是我的真实代码,但与原始代码非常相似。

public class ConnectionFactory{ private static ConnectionFactory instance; public static synchronized ConnectionFactory getInstance(){ if( instance == null ){ instance = new ConnectionFactory(); } return instance; } private ConnectionFactory(){ // private constructor implementation } } 

因为我不太确定静态同步方法的行为,所以我从谷歌得到了一些建议 – 在同一个类中没有(或尽可能少)多个静态同步方法。 我想在实现静态同步方法时,会使用属于Class对象的锁,这样多个静态同步方法可能会降低系统的性能。

我对吗? 或者JVM使用其他机制来实现静态同步方法? 如果我必须在类中实现多个静态同步方法,那么最佳实践是什么?

谢谢你们!

亲切的问候!

最好的方法(尽可能减少代码中的更改)是这样做的:

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

如您所见, getInstance方法现在没有实际需要,因此您可以将代码简化为:

 public class ConnectionFactory{ public static final ConnectionFactory INSTANCE = new ConnectionFactory(); private ConnectionFactory(){ } } 

关于同步的UPD:最好的方法是在外部类不可见的锁上进行同步,即:

 public class ConnectionFactory{ private static final Object lock = new Object(); public static void doSmth() { synchronized (lock) { ... } } public static void doSmthElse() { synchronized (lock) { ... } } } 

有很多讨论“为什么同步this是一个坏主意”(就像这个一样),我认为在课堂上同步也是如此。

有几种方法可以创建单例。

一种推荐的方法是使用枚举(保证只创建一个实例):

 public enum ConnectionFactory { INSTANCE; } 

或者您可以在类加载时静态创建它:

 public class ConnectionFactory { private static ConnectionFactory INSTANCE = new ConnectionFactory(); private ConnectionFactory() {} public static ConnectionFactory getInstance() { return INSTANCE; } } 

如果你需要懒洋洋地加载它你可以使用这个成语(而不是双重检查锁定反模式 )

 public class ConnectionFactory { private static class ConnectionFactoryHolder { private static ConnectionFactory INSTANCE = new ConnectionFactory(); } public static ConnectionFactory getInstance() { return ConnectionFactoryHolder.INSTANCE; } } 

是的,静态方法在其类对象上同步。 我不担心这里的表现,因为这可能不是你的表演热点。 做到简单,优化您需要的时间和地点。

静态同步方法使用类上的锁。 在您的示例中,它将访问ConnectionFactory类对象上的锁。 最佳做法是不要长时间保持锁定。 您是否拥有多个同步方法本身并不是问题。

Effective Java建议使用Enums创建单例。 所以你的代码看起来像这样:

 public enum ConnectionFactory{ INSTANCE; // Other factory methods go here. } 

}