muduo源码分析:ThreadLocalSigleton类

来源:互联网 发布:私有密码算法范畴 编辑:程序博客网 时间:2024/04/30 03:49

单例+特定数据

// Singleton 所管理的对象是 ThreadLocal<Test> ,ThreadLocal<Test> 在进程内是单例,所有线程共一个ThreadLocal<Test>  实例          Singleton调用instance方法获取ThreadLocal<Test>实例,ThreadLocal<Test>实例调用ThreadLocal<Test>::value方法获取Test类型线程特定数据的引用,value返回的是各自线程特定数据引用。Singleton确保进程范围内单例,ThreadLocal<Test>实例只有一个,所有线程共这一个ThreadLocal<Test>实例(所以Singleton内部要加锁初始化实例,或者用pthread_once初始化实例;ThreadLocal确保Test有多个,即在每个线程都有自己特定的(由于ThreadLocal<Test>已经是单例了,定了不会有新的出现了 pthread_key_t key_一直是那一个,所以其实Test在每个线程也是只有一个,也是线程中的单例

#define STL muduo::Singleton<muduo::ThreadLocal<Test> >::instance().value()

多个线程的instance( ) 返回同一个进程范围内单例实例,value( )返回本线程特定数据实例Test的引用

线程特定+单例:ThreadLocalSigleton

所有线程都有自己的一份,且都只有一个,即在线程范围内它是单例,一直存在的,静态的,

ThreadLocalSigleton<Test> ::instance( ): 返回本线程Test单例实例的引用,线程内单例.每次都是这一个static __pthreadT*

ThreadLocal<Test> t:每调用默认构造函数(没有括号,参数),每次都会new 一个Test 实例 t 给本线程


muduo::Singleton<muduo::ThreadLocal<Test> >::instance().value() 与 ThreadLocalSigleton<Test> ::instance( ) 

两者其实都是在线程中实现了单例,效果一样

#ifndef MUDUO_BASE_THREADLOCALSIGLETON_H#define MUDUO_BASE_THREADLOCALSIGLETON_H#include <boost/noncopyable.hpp>#include <assert.h>#include <pthread.h>namespace muduo{template<typename T>class ThreadLocalSingleton : boost::noncopyable{public://注意是静态,获取同一个实例-单例,t_value_ 是__thread 修饰的,线程私有,所以不要加锁static T& instance(){if(t_value_ == NULL){t_value_ = new T();deleter_.set(t_value_);//注册删除释放,t_value_指针在pthread_key_t中也存了一份,用于删除释放内存}return *t_value_;}static T* pointer(){return t_value_;}private://ThreadLocalSingleton只提供了静态方法instance(),获取单例用的是静态方法,没有实例化对象,所以就没有析构,就不要在析构函数中释放T*;即使用成员非静态instance(先实例化ThreadLocalSingleton),如果析构函数中释放了T*,那下次获取的时候会是重新new的,那就不是单例了static void destructor(void* obj){assert(obj == t_value_);//typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];    T_must_be_complete_type tt;(void) tt;delete t_value_;    t_value_ = 0;}class Deleter{public:Deleter(){pthread_key_create(&pkey_, &ThreadLocalSingleton::destructor);}~Deleter(){pthread_key_delete(pkey_);}void set(T* newObj){assert(pthread_getspecific(pkey_) == NULL);pthread_setspecific(pkey_, newObj);}pthread_key_t pkey_;};private:static __thread T* t_value_;//单例,线程生命周期内都只有一个T*,所以要静态static Deleter deleter_;//整个进程只需要一个pthread_key_t key(一级索引),所以静态,某个线程退出就析构某个线程特定数据T* 调用ThreadLocalSingleton::destructor,TSD不是要等进程退出了析构deleter时才一次性全部析构线程特定数据,析构deleter时调用pthread_key_delete(key_)只是删除key。};template<typename T>__thread T* ThreadLocalSingleton<T>::t_value_=NULL;template<typename T>typename ThreadLocalSingleton<T>::Deleter ThreadLocalSingleton<T>::deleter_;//默认构造函数初始化成员变量ThreadLocalSingleton::deleter_; typename 修饰 ThreadLocalSingleton<T>::Deleter表明 Deleter 是模板中的类型}#endif

相关:线程特定数据TSD与__thread

          单例模式

参考:c++教程网

           muduo网络库

           linux多线程服务器端编程》.陈硕


0 0