Singleton设计样式双重检查锁定

问题描述 投票:1回答:4
if (searchBox == null) { //1
synchronized (SearchBox.class) {
    if (searchBox == null) {  //2
        searchBox = new SearchBox();
        }
    }
}

}

这是我的单例模式自定义类。在此代码中,我如上所述使用了双重检查锁定。当我在某些来源上读到许多帖子时,他们说,双重检查很有用,因为它可以防止两个同时运行的并发线程同时产生两个不同的对象。根据线程概念,线程调度程序一次只执行一个线程。然后2个线程将如何尝试执行以上代码。

请向我解释。我理解错了什么?

谢谢:)

java multithreading design-patterns singleton synchronized
4个回答
0
投票

希望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 ...}

0
投票

0
投票

0
投票
© www.soinside.com 2019 - 2024. All rights reserved.