如何在java中同步静态方法

时间:2010-06-02 13:19:21

标签: java multithreading concurrency static synchronized

在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使用其他机制来实现静态同步方法?如果我必须在类中实现多个静态同步方法,那么最佳实践是什么?

谢谢大家!

亲切的问候!

5 个答案:

答案 0 :(得分:7)

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

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是一个坏主意”(如this one),有很多讨论,我认为在课堂上进行同步也是如此。

答案 1 :(得分:3)

您可以通过多种方式创建单身人士。

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

public enum ConnectionFactory {

  INSTANCE;

}

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

public class ConnectionFactory {

  private static ConnectionFactory INSTANCE = new ConnectionFactory();

  private ConnectionFactory() {}

  public static ConnectionFactory getInstance() {
    return INSTANCE;
  }    

}

如果你需要懒洋洋地加载它,你可以使用这个习语(而不是double checked locking anti-pattern

public class ConnectionFactory {

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

  public static ConnectionFactory getInstance() {
    return ConnectionFactoryHolder.INSTANCE;
  }

}

答案 2 :(得分:2)

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

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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

public enum ConnectionFactory{
INSTANCE;

// Other factory methods go here.

}

}