如何在java中同步静态方法

如何在java中同步静态方法,java,multithreading,concurrency,static,synchronized,Java,Multithreading,Concurrency,Static,Synchronized,我在Java中实现单例模式时提出了这个问题。尽管下面列出的示例不是我的真实代码,但与原始代码非常相似 public class ConnectionFactory{ private static ConnectionFactory instance; public static synchronized ConnectionFactory getInstance(){ if( instance == null ){ instance =

我在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
    }
}
因为我不太确定静态同步方法的行为,所以我从google得到了一些建议——不要在同一个类中有(或尽可能少)多个静态同步方法。我猜在实现静态同步方法时,使用了一个属于类对象的锁,这样多个静态同步方法可能会降低系统的性能

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

谢谢大家!

亲切的问候

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

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

    public static ConnectionFactory getInstance(){
        return instance;
    }

    private ConnectionFactory(){
    }
}
public enum ConnectionFactory{
INSTANCE;

// Other factory methods go here.

}
如您所见,现在不需要使用
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) {

           ...
        }
    }
}

有很多关于“为什么在
上同步这个
是个坏主意”(比如)的讨论,我认为在类上同步也是如此。

是的,静态方法是在它们的类对象上同步的。我不担心这里的性能,因为这可能不是您的性能热点。做得简单,需要在何时何地进行优化。

静态同步方法使用类上的锁。在您的示例中,它将访问ConnectionFactory类对象上的锁。最好的做法是不要把锁握得太久。是否有多个同步方法本身不是问题。

有几种方法可以创建单例

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

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

public class ConnectionFactory {

  private static ConnectionFactory INSTANCE = new ConnectionFactory();

  private ConnectionFactory() {}

  public static ConnectionFactory getInstance() {
    return INSTANCE;
  }    

}
如果需要懒洋洋地加载它,可以使用这个习惯用法(而不是

有效的Java建议使用枚举创建单例。因此,您的代码将如下所示:

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

    public static ConnectionFactory getInstance(){
        return instance;
    }

    private ConnectionFactory(){
    }
}
public enum ConnectionFactory{
INSTANCE;

// Other factory methods go here.

}

}

如果唯一的构造函数抛出异常,它将如何创建
实例
。@unbeli:这是我的错误,已更正。但如果您甚至不需要实例,则if是正确的解决方案。@unbeli:使用私有静态工厂方法或静态初始值设定项块。不幸的是,所有这些关于Java内存模型和双重检查锁定的讨论已经用成百上千的代码示例污染了互联网,现在给新手的印象是,在getInstance()方法中懒洋洋地初始化单例实际上是一个好主意,甚至是一种规范。您正确的方法是可以的,只是它不是懒惰的,因此,它并不完全解决OPproblem@Scobal:阅读链接讨论。简而言之:如果另一个类中的其他人将
synchronized(ConnectionFactory.class){}
,则在ConnectionFactory.class上进行同步可能会造成死锁。您的实际代码是否也与延迟初始化有关?因为这通常是对代码和开发人员时间的浪费;在声明中初始化字段99%的时间都是正确的,这使得同步变得不必要。