C++ 中的线程安全单例实现

Posted

技术标签:

【中文标题】C++ 中的线程安全单例实现【英文标题】:Thread safe singleton implementation in 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 类型的本地静态。 【参考方案1】:

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

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

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

http://blogs.msdn.com/oldnewthing/archive/2004/03/08/85901.aspx

【讨论】:

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

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

【讨论】:

【参考方案3】:

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

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

【讨论】:

【参考方案4】:

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

【讨论】:

以上是关于C++ 中的线程安全单例实现的主要内容,如果未能解决你的问题,请参考以下文章

C++ 线程安全的单例模式总结

这才是现代C++单例模式简单又安全的实现

C++的单例模式与线程安全单例模式(懒汉/饿汉)

在 C++ 中,要确保单例线程安全,该怎么做?

多线程阻塞队列定时器线程安全的单例模式的原理及实现

多线程阻塞队列定时器线程安全的单例模式的原理及实现