【问题标题】:Thread safe singleton implementation in C++C++ 中的线程安全单例实现
【发布时间】:2009-06-27 12:02:16
【问题描述】:

以下是众所周知的 C++ 中单例模式的实现。
但是,我不完全确定它是否是线程安全的。
根据之前在此处提出的类似问题的答案,它似乎是线程安全的。
是这样吗?

//Curiously Recurring Template Pattern    
//Separates a class from its Singleton-ness (almost).    
#include <iostream>  
using namespace std;

template<class T> class Singleton {
  Singleton(const Singleton&);
  Singleton& operator=(const Singleton&);
protected:
  Singleton() {}
  virtual ~Singleton() {}
public:
  static T& instance() {
    static T theInstance;
    return theInstance;
  }
};

// A sample class to be made into a Singleton
class MyClass : public Singleton<MyClass> {
 int x;
protected:
  friend class Singleton<MyClass>;
  MyClass() { x = 0; }
public:
 void setValue(int n) { x = n; }
  int getValue() const { return x; }
};

【问题讨论】:

  • 你为什么要把它做成一个 WIKI?这是一个完全有效的问题。
  • 你没有给出任何理由说明认为模式实现不是线程安全的。请做。
  • 这里的朋友班的目的是什么?有人可以回答吗?
  • 哦,拍!应该检查常见问题以了解它的含义,而不是假设它是什么。
  • @Ahmed。它用于编译语句“static T theInstance”。如您所见,MyClass 具有受保护的构造函数,因此我们需要朋友说明符,以便 Singleton 类(准确地说是 Singleton)可以声明 MyClass 类型的本地静态。

标签: c++ multithreading design-patterns


【解决方案1】:

不,这不是线程安全的,因为静态本地没有以任何方式受到保护。默认情况下,静态本地不是线程安全的。这意味着您可能会遇到以下问题

  • 单例的构造函数多次运行
  • 不能保证对静态的分配是原子的,因此您可以在多线程场景中看到部分分配
  • 我可能还缺少一些。

这是 Raymond Chen 的详细博客文章,介绍了为什么 C++ 静态在默认情况下不是线程安全的。

【讨论】:

  • 所以基本上这意味着不可能使用 C++ 做一个与操作系统无关的单例?也就是说,你总是需要一些关键部分或类似的部分来做一个?
【解决方案2】:

不是线程安全的。 为了变得线程安全,您应该在锁之前添加一个检查(信号量锁)并在锁之后添加另一个检查。然后您可以确定,即使在来自不同线程的同时调用中,您也可以提供一个实例。

【讨论】:

    【解决方案3】:

    它不是线程安全的,除非您将编译器配置为为静态访问生成线程安全代码。

    不过,代码最好是独立的,所以我会在这里和那里添加一个互斥锁。

    【讨论】:

      【解决方案4】:

      如果您仍然对此主题感兴趣并且正在使用 C++ 11 标准编译器,您可以找到 here 一个关于多线程环境中单例模式的提议。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-12
        • 2011-01-13
        相关资源
        最近更新 更多