Java 对于单例模式,使用双重检查锁定习惯用法是否最佳?
对单例模式使用双重检查锁定习惯用法更好吗?还是同步方法 即: } 或Java 对于单例模式,使用双重检查锁定习惯用法是否最佳?,java,synchronization,locking,singleton,Java,Synchronization,Locking,Singleton,对单例模式使用双重检查锁定习惯用法更好吗?还是同步方法 即: } 或 基本上,您的第二个选项不会增加额外的保证 您会更频繁地检查,但并发访问仍可能发生在它们之间,因此,您正在减少两个实例发生的概率,但并没有消除它。让类加载器为您完成这项工作: /* * This solution takes advantage of the Java memory model's guarantees about class initialization * to ensure th
基本上,您的第二个选项不会增加额外的保证
您会更频繁地检查,但并发访问仍可能发生在它们之间,因此,您正在减少两个实例发生的概率,但并没有消除它。让类加载器为您完成这项工作:
/*
* This solution takes advantage of the Java memory model's guarantees about class initialization
* to ensure thread safety. Each class can only be loaded once, and it will only be loaded when it
* is needed. That means that the first time getInstance is called, mySingletonServiceLoader
* will be loaded and instance will be created, and since this is controlled by ClassLoaders,
* no additional synchronization is necessary.
*/
public static DocumentService getInstance() {
return mySingletonServiceLoader.INSTANCE;
}
private static class mySingletonServiceLoader {
static DocumentService INSTANCE = new DocumentService();
}
}
第一个选项。 可以创建单个实例的多个版本 在
getInstance
()调用中,检查实例是否为null
,如果为null,则立即构造实例,然后返回实例
它应该是线程安全的
另请参阅。第一个选项是正确的双重检查锁定实现,但是如果ProcessManager类中除了getInstance之外没有其他公共方法,那么您只需要
public class ProcessManager {
private static ProcessManager instance;
static {
instance = new ProcessManager();
}
private ProcessManager() {
}
public static ProcessManager getInstance() {
return instance;
}
}
该类将在第一次ProcessManager.getInstance()调用时加载和初始化如果需要延迟加载,我将坚持双重检查而不是同步方法。最后,问题是:
Volatile,简单地强制对Volatile变量的所有访问(读或写)发生在主内存中,有效地将Volatile变量从CPU缓存中清除。这对于一些只要求变量的可见性正确且访问顺序不重要的操作非常重要
初始化实例后,将不执行同步块(但对于争用条件)。要支付的唯一并发成本是对volatile变量的单次读取
注意,在有效的Java中,Bloch说在局部变量中加载volatile字段可以提高性能(我理解这是因为volatile读取较少)
在你的第二段代码中,有两个嵌套的if,中间没有任何东西是没有意义的。正如你在上一个问题中所解释的,以上都没有。在你的第二个例子中,不需要进行双重检查(假设你没有在你的类中的任何其他地方接触singleton成员)因为你已经处于危急关头了section@a_horse_with_no_name不,它没有,即使考虑到线程问题。我在某个地方读到,不记得在哪里,初始化singleton的最好方法是静态初始化它。在本例中,private static processManager singleton=new processManager()
/*
* This solution takes advantage of the Java memory model's guarantees about class initialization
* to ensure thread safety. Each class can only be loaded once, and it will only be loaded when it
* is needed. That means that the first time getInstance is called, mySingletonServiceLoader
* will be loaded and instance will be created, and since this is controlled by ClassLoaders,
* no additional synchronization is necessary.
*/
public static DocumentService getInstance() {
return mySingletonServiceLoader.INSTANCE;
}
private static class mySingletonServiceLoader {
static DocumentService INSTANCE = new DocumentService();
}
}
public class ProcessManager {
private static ProcessManager instance;
static {
instance = new ProcessManager();
}
private ProcessManager() {
}
public static ProcessManager getInstance() {
return instance;
}
}
public static ProcessManager getInstance() throws Exception {
ProcessManager result = singleton;
if (result == null) {
synchronized (MyClass.class) {
result = singleton;
if (result == null) {
singleton = result = new ProcessManager();
}
}
return result;
}