【问题标题】:Is it this safe to do C++ Singleton first instance creation?创建 C++ Singleton 第一个实例是否安全?
【发布时间】:2014-10-23 01:55:39
【问题描述】:

据我了解,如果 Singleton::instance() 在不同的线程中调用,如果两个调用都引用实际实例的第一个构造,则可能会出现一些问题。

因此,如果我将第一个 Singleton::instance() 调用移动到甚至没有创建其他线程的程序的最开头,现在这会是线程安全的吗?

当然,它的所有成员变量在使用时都受到互斥守卫的保护。

【问题讨论】:

  • 通常的线程安全单例安装模式是 Scott Meyer 的(请以see here 为例)。
  • 像往常一样,你的首要任务应该是认真思考你是否真的需要它。我会说至少 90% 的时间是净损失,不仅增加了它自身的复杂性,而且至少与不使客户端代码更复杂一样频繁。

标签: c++ multithreading


【解决方案1】:

这可能会让您大开眼界,发现线程安全的 Singleton 并不容易。 http://silviuardelean.ro/2012/06/05/few-singleton-approaches/

与以前一样,如果您要求在启动任何线程之前创建它,它就不是很健壮。

值得注意的是,如果您使用 C++11 进行编译,那么按照 Brian 所说的(静态存储 + 静态方法)进行操作可以保证线程安全。对于任何以前的版本,您都需要一个互斥锁,并且会遇到我分享的链接中提到的警告。

【讨论】:

    【解决方案2】:

    因此,如果我将第一个 Singleton::instance() 调用移动到甚至没有创建其他线程的程序的最开头,那么现在这是否是线程安全的?

    是的,但这个元素不在Singleton 的设计之内,如果是这样,它可能会更健壮。

    您通常可以在 static 方法中使用 static 存储在文件范围或函数范围内分配它。验证您的编译器是否围绕它生成排除项或在那里添加您自己的互斥锁。

    【讨论】:

      【解决方案3】:

      是的,当您可以保证只有一个线程存在时执行初始实例化可以清楚地保护它免受导致竞争条件的其他线程的影响。

      不过,它感觉不是很健壮。至少,在该区域贴上警告 cmets。

      【讨论】:

        【解决方案4】:

        也许你不需要单例实例的延迟初始化?

        如果你真的想要它,那么你可以在构造它时使用互斥锁保护单例实例。

        【讨论】:

          【解决方案5】:

          请记住不要放在标题中。
          如果你把实现放在头文件中,它可能会在每个使用它的编译单元中生成。这意味着它不会是单身。

          也不要在静态库中编译它。如果代码被链接并合并到多个非静态库中,这也可能导致多个实例。

          【讨论】:

            【解决方案6】:

            如果还没有创建额外的线程,并且您在创建这些线程之前进行了该操作,那么我看不到在任何新创建的多线程环境中使用您已经创建的单例可能会遇到问题的真实场景。

            单例模式进入多线程环境的主要线程安全问题是关于如何防止不同线程创建两个或多个“单例”实例。我已经在“多线程环境”部分here 中描述了这种情况。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-11-24
              • 1970-01-01
              • 2015-07-17
              • 1970-01-01
              • 1970-01-01
              • 2012-08-24
              相关资源
              最近更新 更多