如何分配线程本地存储?

| 我的函数中有一个静态变量,但我希望每个线程都将其设为静态。 如何为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
是便携式解决方案的最佳方法。 在Linux和GCC上,您可以使用
__thread
修饰符。 因此,您的实例变量将如下所示:
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指定了“ 2”存储类型,只需使用它即可。
AnotherClass::threadSpecificAction()
{
  thread_local MyClass *instance = new MyClass();
  instance->doSomething();
}
一种可选的优化方法是也在线程本地存储上进行分配。     
如果您使用的是MSVC ++,则可以阅读线程本地存储(TLS) 然后您可以看到此示例。 另外,请注意TLS的规则和限制     
在Windows上,可以使用TlsAlloc和TlsFree在线程本地存储中分配存储。 要使用TLS设置和检索值,可以分别使用TlsSetValue和TlsGetValue 在这里,您可以看到有关如何使用它的示例。     
只是一个旁注... MSVC ++支持VSC ++ 2005中的declspec(thread)
#if (_MSC_VER >= 1400)
  #ifndef thread_local     
    #define thread_local __declspec(thread)
  #endif
#endif
主要问题是(在boost :: thread_specific_ptr中解决了)标有它的变量不能包含ctor或dtor。     
Folly(Facebook开放源代码库)具有线程本地存储的可移植实现。 根据其作者:   改进了非平凡类型的线程本地存储(速度与   
pthread_getspecific
,但只消耗一个
pthread_key_t
,快4倍   比
boost::thread_specific_ptr
)。 如果您正在寻找本地存储线程的可移植实现,则此库是一个不错的选择。     

要回复问题请先登录注册