来自C ++的Java新手,遇到了这个同步的块示例(更多关于此page的上下文)。我的问题是:
不应该" if"声明也包含在" synchronized块中#34;?或者其他线程可以执行同一段代码,传递"如果"检查站并认为" _instance"是null然后在当前线程完成执行synchronized块(并创建一个新实例)后,其他线程将创建重复的实例?谢谢!击>
现在我意识到代码实际上正在进行双重检查,我有一个新问题,为什么需要进行双重检查?谢谢!
代码块复制如下:
public class Singleton{
private static volatile Singleton _instance;
public static Singleton getInstance(){
if(_instance == null){ //Shouldn't this line be included in the synchronized block?
synchronized(Singleton.class){
if(_instance == null) _instance = new Singleton();
}
}
return _instance;
}
答案 0 :(得分:0)
如果在_instance == null
块中包含语句synchronized
,它将为每个请求/调用{添加不必要的开销(获取锁定并实现锁定) {1}}方法,即只有当您知道尚未创建对象时,才会获取/释放锁定(在 Singleton 对象上),因此无需不必要地获取锁定并检查它是否已经getInstance()
。
为什么需要进行双重检查?
假设您只进行一次检查,如下所示:
null
现在问题是代码需要获取/释放对方法进行的每次调用的锁定(在public static Singleton getInstance(){
synchronized(Singleton.class){
if(_instance == null) //SINGLE IF CHECK
_instance = new Singleton();
}
return _instance;
}
类上),这不是必需的,因为一旦在第一次调用方法时创建了Singleton
个实例(使用新的Singleton
), Singleton()
不会是_instance
。因此,通过在null
之上添加附加条件_instance == null
,它将避免以后每次调用的不必要的锁定开销,这个概念众所周知为双重检查锁定。 / p>
我建议你也阅读here(下面复制的文字,强调我的文字),并阅读重复link以更好地理解这个概念。
双重检查锁定习语是用于的软件设计模式 通过首先测试锁定来减少获取锁的开销 没有实际获得锁定的标准。 双重检查锁定 通过将同步限制为罕见的情况来提高性能 计算字段的值或构造一个新的实例 在共同的期间引用和通过前述同步的字段 检索已经创建的实例或值的情况。