C++中多线程与Singleton的那些事儿

发表于:2015-3-11 10:08

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:origins    来源:51Testing软件测试网采编

  前言
  前段时间在网上看到了个的面试题,大概意思是如何在不使用锁和C++11的情况下,用C++实现线程安全的Singleton。
  看到这个题目后,第一个想法就是用Scott Meyer在《Effective C++》中提到的,在static成员函数中构造local static变量的方法来实现,但是经过一番查找、思考,才明白这种实现在某些情况下是有问题的。本文主要将从最基本的单线程中的Singleton开始,慢慢讲述多线程与Singleton的那些事。
  单线程
  在单线程下,下面这个是常见的写法:
template<typename T>
class Singleton
{
public:
static T& getInstance()
{
if (!value_)
{
value_ = new T();
}
return *value_;
}
private:
Singleton();
~Singleton();
static T* value_;
};
template<typename T>
T* Singleton<T>::value_ = NULL;
  在单线程中,这样的写法是可以正确使用的,但是在多线程中就不行了。
  多线程加锁
  在多线程的环境中,上面单线程的写法就会产生race condition从而产生多次初始化的情况。要想在多线程下工作,最容易想到的就是用锁来保护shared variable了。下面是伪代码:
template<typename T>
class Singleton
{
public:
static T& getInstance()
{
{
MutexGuard guard(mutex_)  // RAII
if (!value_)
{
value_ = new T();
}
}
return *value_;
}
private:
Singleton();
~Singleton();
static T*     value_;
static Mutex  mutex_;
};
template<typename T>
T* Singleton<T>::value_ = NULL;
template<typename T>
Mutex Singleton<T>::mutex_;
  这样在多线程下就能正常工作了。这时候,可能有人会站出来说这种做法每次调用getInstance的时候都会进入临界区,在频繁调用getInstance的时候会比较影响性能。这个时候,为了解决这个问题,DCL写法就被聪明的先驱者发明了。
41/41234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号