searchBox = new SearchBox();
if (searchBox == null) { //1
synchronized (SearchBox.class) {
if (searchBox == null) { //2
searchBox = new SearchBox();
}
}
}
}
这是我的单例模式自定义类。在此代码中,我如上所述使用了双重检查锁定。当我在某些来源上读到许多帖子时,他们说,双重检查很有用,因为它可以防止两个同时运行的并发线程同时产生两个不同的对象。根据线程概念,线程调度程序一次只执行一个线程。然后2个线程将如何尝试执行以上代码。
请向我解释。我理解错了什么?
谢谢:)
您不希望2个线程执行代码同时。这是一个singleton。 单吨。在任何给定时间都应该只存在该对象的一个实例。如果两个线程同时运行相同的代码,则它们可能会意外地创建两个searchBox
,然后这不是一个[ton],是吗? synchronized
允许您做的是确保单例的初始化是线程安全的(不是序列化安全或基于枚举的单例获得的所有其他好处)。通过线程安全,这意味着您将不会获得2个线程运行代码[[同时
除了对 其他任何试图查看 没有同步]的线程,很容易看到这些分配发生的情况[[以不同的顺序searchBox = new SearchBox();
searchBox
的赋值,还将有其他几种赋值来初始化新的SearchBox
实例。searchBox
这意味着,如果线程A创建单例,然后线程B出现并随后找到searchBox != null
,则线程B将不是进入synchronized
块,而线程B 可以看到单身对象处于未初始化或部分初始化的状态。
单例对象必须为safely published。安迪·特纳(Andy Turner)对原始问题的评论(见上文)列举了几种不同的方法来实现这一目标。
您发布的代码段是线程安全的。即使您删除外部if
条件,也将只有一个Searchbox实例。
if (searchBox == null) { //1
synchronized (SearchBox.class) {
if (searchBox == null) { //2
searchBox = new SearchBox();
}
}
那么为什么我们需要外部if
条件?
假设我们首先没有创建块和searchbox
对象。线程将由于同步阻塞而被阻塞。在这种情况下,外部if
块将停止线程进入等待阶段。
替代方法是,可以使用静态内部类来实现Singleton模式public class Singleton {
private static class SingletonHolder {
public static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
以上代码段的来源:why is static inner class singleton thread safe
类加载器将首先加载静态字段,因此该实例将在任何线程调用方法getInstance()之前可用。因此,对于有效而干净的Singleton,请考虑使用此技术,并避免所有昂贵的同步操作
public class SearchBox{ private static SearchBox instance = new SearchBox(); private SearchBox(){throw new OperationNotAllowedException();} public static SearchBox getInstance(){ return instance; } public SomeReturn instanceMethod(){return ...}