muduo网络库:05---线程同步精要之(线程安全的Singleton实现)
原创
©著作权归作者所有:来自51CTO博客作者董哥的黑板报的原创作品,请联系作者获取转载授权,否则将追究法律责任
- 本文内容衔接于前一篇文章(封装MutexLock、MutexLockGuard、Condition)
一、DCL
- 研究Singleton的线程安全实现的历史会发现很多有意思的事情,人们一度认为double checked locking(缩写为DCL)是王道,兼顾了效率与正确性。后来有“神牛”指出由于乱序执行的影响,DCL是靠不住的。可以参阅:
二、pthread_once
- 其实没有那么麻烦,在实践中用pthread_once就行:
template<typename T>
class Singleton :boost::noncopyable {
private:
static T& instance()
{
pthread_once(&ponce_, &Signleton::init);
return *value_;
}
private:
Singleton();
~Singleton();
static void init()
{
value_ = new T();
}
private:
static pthread_oncet ponce_;
static T* value_;
};
template<typename T>
pthread_oncet Singleton<T>::ponce_ = PTHREAD_ONCE_INIT;
template<typename T>
T* Singleton<T>::value_ = NULL;
- 它用pthread_once_t来保证 lazy-initialization的线程安全
- 线程安全性由Pthreads库保证,如果系统的Pthreads库有bug,那就认命吧,多线程程序反正也不可能正确执行了
Foo& foo = Singleton<Foo>::instance();
- 在长时间运行的服务器程序里,这不是一个问题,反正进程也不打算正常退出(参阅后面的“分布式系统工程实践之能随时重启进行作为系统的重要目标”)
- 在短期运行的程序中,程序退出的时候自然就释放所有资源了(前提是程序里不使用不能由操作系统自动关闭的资源,比如跨进程的mutex)
- 在实际的muduo::Singleton class中,通过atexit提供了销毁功能,聊胜于无罢了
- 另外,这个Singleton只能调用默认构造函数,如果用户想要指定T的构造方式,我们可以用模板特化技术来提供 一个定制点,这需要引入另一层间接
三、附加
- 本专题未完结,参阅下一篇文章(借shared_ptr实现copy-on-write)