Muduo之封装ThreadLocal、ThreadLocalSingleton
2018-02-08 15:22
162 查看
基础知识:
Linux线程基础知识
每一个线程都有各自的var,从输出可以看出。
线程本地单例类的实现,也比较简单,有了前面Singleton的实现,所以这里也很清楚。注意此实现用了
Linux线程基础知识
1、ThreadLocal
ThreadLocal可以叫做Thread的局部变量,通过ThreadLocal创建的对象每个线程都拥有其副本被各自线程独有,操作其对象不会造成线程不安全。这是通过封装Linux操作系统提供的线程特定数据实现,封装也比较简单,不涉及技巧。template<typename T> class ThreadLocal : boost::noncopyable//禁止拷贝和赋值 { public: ThreadLocal() { MCHECK(pthread_key_create(&pkey_, &ThreadLocal::destructor)); /* 创建线程键,此键由当前进程全部线程共有。 可以通过此键索引线程特定数据。 */ } ~ThreadLocal() { MCHECK(pthread_key_delete(pkey_));//取消键与线程特定数据的关联 } T& value()//APUE中常用做法 { T* perThreadValue = static_cast<T*>(pthread_getspecific(pkey_));//获取特定数据区域 if (!perThreadValue)//如果没有分配对象空间,那么分配。 { T* newObj = new T();//分配空间,并对应构造函数初始化 MCHECK(pthread_setspecific(pkey_, newObj));//将分配区域和键连接起来 perThreadValue = newObj; } return *perThreadValue;//返回对象的引用。 } private: static void destructor(void *x)//析构函数,x必须强制转换,告诉编译器内存组织关系 { T* obj = static_cast<T*>(x); typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];//判断传入对象是否有定义 T_must_be_complete_type dummy; (void) dummy; delete obj;//对应new操作 } private: pthread_key_t pkey_;//线程键 };
2、ThreadLocalSingleton
__thread关键字
__thread是GCC内置的线程局部存储设施,存取效率可以和全局变量相比。
__thread变量每一个线程有一份独立实体,各个线程的值互不干扰。可以用来修饰那些“带有全局性且值可能变,但是又不值得用全局锁保护”的变量。
__thread使用规则:只能修饰POD类型(类似整型指针的标量,不带自定义的构造、拷贝、赋值、析构的类型,二进制内容可以任意复制memset,memcpy,且内容可以复原),不能修饰class类型,因为无法自动调用构造函数和析构函数,可以用于修饰全局变量,函数内的静态变量,不能修饰函数的局部变量或者class的普通成员变量,且
__thread变量值只能初始化为编译器常量。
__thread string t_obj1("Chen Shuo");//错误,不能调用对象的构造函数 __thread string* t_obj2 = new string;//错误,初始化必须用编译期常量 __thread string* t_obj3 = NULL;//正确,但是需要手工初始化并销毁对象 __thread int i = 5;//正确
#include<iostream> #include<pthread.h> #include<unistd.h> using namespace std; __thread int var = 1;//全局修饰,不必用锁保护,线程各自拥有副本 void* worker1(void* arg){ cout<< ++var <<endl;//输出2 } void* worker2(void* arg){ cout<< ++var <<endl;//输出2 } int main(){ pthread_t pid1,pid2; static __thread int temp=10;//修饰函数内的static变量 pthread_create(&pid1,NULL,worker1,NULL); pthread_join(pid1,NULL); pthread_create(&pid2,NULL,worker2,NULL); pthread_join(pid2,NULL); cout<< var <<endl;//输出1 return 0; }
每一个线程都有各自的var,从输出可以看出。
线程本地单例类的实现,也比较简单,有了前面Singleton的实现,所以这里也很清楚。注意此实现用了
__thread修饰指针已经确保的线程安全,所以没有用
pthread_once。
template<typename T> class ThreadLocalSingleton : boost::noncopyable//禁止拷贝,禁止赋值 { public: static T& instance()//返回单例对象,不需要按照线程安全方式实现,本身就是__thread类型线程安全 { if (!t_value_) { t_value_ = new T(); deleter_.set(t_value_); } return *t_value_; } static T* pointer()//返回指针 { return t_value_; } private: ThreadLocalSingleton(); //禁止构造 ~ThreadLocalSingleton();//禁止析构 static void destructor(void* obj)//通过RAII手法封装pthread_key_create和pthread_key_delete,供类调用 { assert(obj == t_value_); typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1]; T_must_be_complete_type dummy; (void) dummy; 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_; }; static __thread T* t_value_;//__thread关键字保证线程局部属性,只能修饰POD类型 static Deleter deleter_;//用来销毁T*指针所指对象 }; template<typename T> __thread T* ThreadLocalSingleton<T>::t_value_ = 0;//初始化为空 template<typename T> typename ThreadLocalSingleton<T>::Deleter ThreadLocalSingleton<T>::deleter_;//定义,然后默认调用Deleter构造函数,创建键。
相关文章推荐
- muduo网络库学习之ThreadLocal<T> 类、ThreadLocalSingleton<T>类封装知识点
- InheritableThreadLocal类和ThreadLocal类
- ThreadLocal和InheritableThreadLocal使用
- ThreadLocal 和 InheritableThreadLocal (引用)
- Android ThreadLocal及InheritableThreadLocal分析
- ThreadLocal、ThreadLocalMap、Thread关系详细解析
- Android 详解ThreadLocal及InheritableThreadLocal
- 多线程(八)~ThreadLocal、InheritableThreadLocal的使用
- muduo源码分析:线程类Thread封装
- Muduo之封装CurrentThread、Thread、ThreadPool
- muduo库源码学习(base)ThreadLocalSingleton
- ThreadLocal与InheritableThreadLocal的区别
- ThreadLocal与InheritableThreadLocal学习笔记
- ThreadLocal与InheritableThreadLocal的使用
- Java多线程之ThreadLocal和InheritableThreadLocal的使用
- 深入解析 ThreadLocal 和 ThreadLocalMap
- ThreadLocal源码解析,以及ThreadLocal、ThreadLocalMap、Thread 三者之间的关系
- ThreadLocal与Inheritable ThreadLocal
- ThreadLocal和InheritableThreadLocal的区别
- ThreadLocal,ThreadLocalMap,Thread 的相互关系以及设计原理分析