11

他们说早期绑定解决了同步问题。我无法理解“如何”。这对 Java 来说是特殊的,还是同样适用于 C++?

那么,使用这种方法我们实际上不需要互斥锁吗?

在此处输入图像描述

4

5 回答 5

11

JVM 确保在允许通过其他线程对其进行任何访问之前,每个类都已完全加载。这意味着所有静态变量,包括uniqueInstance上面的,在它们可以被访问之前完全实例化。这是 Java 特有的,意味着您不需要同步来保护实例的发布。

于 2012-05-07T08:40:14.303 回答
3

我认为他们指的是在启动/创建任何线程之前创建 Singleton 实例,从而减轻了创建时同步的需要。

编辑:添加有关 C++ 和静态变量的信息

在 C++ 中,静态变量也在执行之前被初始化,就像 David Harkness 提到的 Java 一样。C++ 中的一个问题可能是在嵌入式环境中,直到系统初始化之后才能执行对 malloc/new 的调用,在这种情况下,使用单例静态初始化程序可能会出现问题。

于 2012-05-07T08:40:59.393 回答
0

惰性实例化试图解决的一件事(不仅与 C++ 相关)是静态初始化顺序 fiasco。这是一个问题,您几乎无法控制初始化顺序(使用多个翻译单元),但依赖关系可能需要一个对象在创建另一个对象之前已经存在。使用惰性实例化,对象是根据需要创建的,所以只要没有循环依赖,应该没问题。

如果依赖项对您来说是个问题,并且您仍然希望避免为每个 getInstance() 锁定成本,您仍然可以通过在类中添加 Initialize() 函数在启动线程之前初始化所有单例来进行即时实例化。通过这种方式,您可以使用断言检查单例仅初始化一次并且仅在初始化后访问。

请注意:

  • 共享资源在被访问时仍应被锁定。
  • 从 C++11 开始(以及当我不确定其他编译器时使用 gcc 时),最简单的解决方案是在 getInstance 中使用静态函数变量并返回对该变量的引用。这是线程安全的。

    class Example
    {
      ...
      static Example& getInstance()
      {
        static Example instance;
        return instance;
      }
    };
    
于 2012-05-07T11:28:06.200 回答
0

答案是YES!。使用这种方法,您将不需要锁定“获取实例”
--编辑--
原因是对象的创建是操作系统加载过程的一部分,可确保在您的代码运行之前加载它。
Ps 它也适用于 C++。
注意:
1.“获取实例”不需要锁,但如果实例有共享成员,则可能需要。
2.这只有在你不需要参数来初始化实例的情况下才有可能。

于 2012-05-07T08:43:34.680 回答
-2

如果您希望 singelton 成员在第一次调用之前保持为空,您可以只同步创建。例如

getInstance() {
     if (singleton == null) {
         lock();
         if (singleton == null) {
               singleton = new Singleton();
         }
         unlock();
     }
     return singleton;
}
于 2012-05-07T08:38:33.187 回答