单件模式是非线程安全的:
// Single threaded version class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) { helper = new Helper(); } return helper; } // other functions and members... }
// Correct but possibly expensive multithreaded version class Foo { private Helper helper = null; public synchronized Helper getHelper() { if (helper == null) { helper = new Helper(); } return helper; } // other functions and members... }
// Broken multithreaded version // "Double-Checked Locking" idiom class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) { helper = new Helper(); } } } return helper; } // other functions and members... }
使用pthread_once语义可以解决上述问题:The purpose of pthread_once(pthread_once_t *once_control, void (*init_routine) (void)) is to ensure that a piece of initialization code is executed at most once. The once_control argument points to a static or extern variable statically initialized to PTHREAD_ONCE_INIT.The first time pthread_once is called with a given once_control argument, it calls init_routine with no argument and changes the value of the once_control variable to record that initialization has been performed. Subsequent calls to pthread_once with the sameonce_control argument do nothing.
线程安全的例子:
#include<iostream> #include<pthread.h> #include<unistd.h> #include<stdlib.h> #include<boost/noncopyable.hpp> using namespace std; using namespace boost; template<typename T> class singleton:noncopyable{ public: static T& instance(){ pthread_once(&ponce,&singleton::init);//第一次调用才会执行init,此后将改变ponce并将已经执行记录存入ponce return *value; } private: singleton(); ~singleton(); static void init(){ value=new T();//这里只能调用T的默认构造函数,若要用户指定T的构造方式,可能需要模板特化...不怎么熟悉...汗 } private: static pthread_once_t ponce; static T* value; }; template<typename T>//静态成员类外初始化 pthread_once_t singleton<T>::ponce=PTHREAD_ONCE_INIT;//ponce初始化 template<typename T> T* singleton<T>::value=NULL; class test{//测试对象 public: void show(){ cout<<"show()"<<endl; } }; int main(){ test& p=singleton<test>::instance();//注意使用方法 p.show(); test& q=singleton<test>::instance(); if(&p==&q) cout<<"singleton success"<<endl; else cout<<"singleton failure"<<endl; return 0; }