如何分配线程本地存储?
我在我的函数中有一个variables是静态的,但我希望它在每个线程的基础上是静态的。
我怎样才能为我的C ++类分配内存,使得每个线程都有自己的类实例副本?
AnotherClass::threadSpecificAction() { // How to allocate this with thread local storage? static MyClass *instance = new MyClass(); instance->doSomething(); }
这是在Linux上。 我没有使用C ++ 0x,这是gcc v3.4.6。
#include <boost/thread/tss.hpp> static boost::thread_specific_ptr< MyClass> instance; if( ! instance.get() ) { // first time called by this thread // construct test element to be used in all subsequent calls from this thread instance.reset( new MyClass); } instance->doSomething();
值得注意的是C ++ 11引入了thread_local
关键字。
以下是存储时间说明符的一个示例:
#include <iostream> #include <string> #include <thread> #include <mutex> thread_local unsigned int rage = 1; std::mutex cout_mutex; void increase_rage(const std::string& thread_name) { ++rage; std::lock_guard<std::mutex> lock(cout_mutex); std::cout << "Rage counter for " << thread_name << ": " << rage << '\n'; } int main() { std::thread a(increase_rage, "a"), b(increase_rage, "b"); increase_rage("main"); a.join(); b.join(); return 0; }
可能的输出:
Rage counter for a: 2 Rage counter for main: 2 Rage counter for b: 2
boost::thread_specific_ptr
是便携式解决scheme的最佳方式。
在Linux和GCC上,你可以使用__thread
修饰符 。
所以你的实例variables将如下所示:
static __thread MyClass *instance = new MyClass();
如果您正在使用Pthreads,则可以执行以下操作:
//declare static data members pthread_key_t AnotherClass::key_value; pthread_once_t AnotherClass::key_init_once = PTHREAD_ONCE_INIT; //declare static function void AnotherClass::init_key() { //while you can pass a NULL as the second argument, you //should pass some valid destrutor function that can properly //delete a pointer for your MyClass pthread_key_create(&key_value, NULL); } void AnotherClass::threadSpecificAction() { //Initialize the key value pthread_once(&key_init_once, init_key); //this is where the thread-specific pointer is obtained //if storage has already been allocated, it won't return NULL MyClass *instance = NULL; if ((instance = (MyClass*)pthread_getspecific(key_value)) == NULL) { instance = new MyClass; pthread_setspecific(key_value, (void*)instance); } instance->doSomething(); }
C ++ 11指定了一个thread_local
存储types,只是使用它。
AnotherClass::threadSpecificAction() { thread_local MyClass *instance = new MyClass(); instance->doSomething(); }
一个可选的优化也是在线程本地存储上分配。
如果您正在使用MSVC ++,则可以阅读线程本地存储(TLS)
然后你可以看到这个例子 。
此外,请注意TLS的规则和限制
在Windows上,您可以使用TlsAlloc和TlsFree在线程本地存储中分配存储空间。
要使用TLS设置和检索值,可以分别使用TlsSetValue和TlsGetValue
在这里你可以看到一个关于如何使用的例子。
只是一个侧面说明… MSVC ++支持从VSC ++ 2005 declspec(线程)
#if (_MSC_VER >= 1400) #ifndef thread_local #define thread_local __declspec(thread) #endif #endif
主要的问题是(这是解决在boost :: thread_specific_ptr)标有它的variables不能包含ctor或dtor。
愚蠢的(Facebook的开源库)有一个线程本地存储的便携式实现。
根据其作者:
改进了非平凡types的线程本地存储(类似于
pthread_getspecific
速度,但只消耗一个pthread_key_t
,比boost::thread_specific_ptr
快4倍)。
如果你正在寻找一个本地存储线程的可移植实现,这个库是一个不错的select。