57

我的函数中有一个静态变量,但我希望它在每个线程的基础上都是静态的。

如何为我的 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。

4

9 回答 9

70
#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();
于 2011-05-16T18:26:35.333 回答
66

值得注意的是,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
于 2013-03-29T06:01:44.560 回答
14

boost::thread_specific_ptr是便携式解决方案的最佳方式。

在 Linux 和 GCC 上,您可以使用__thread修饰符

因此,您的实例变量将如下所示:

static __thread MyClass *instance = new MyClass();
于 2011-05-18T07:55:40.947 回答
11

如果您使用 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();
}
于 2011-05-16T18:26:58.047 回答
4

如果您正在使用 MSVC++,您可以阅读线程本地存储 (TLS)

然后你可以看到这个例子

另外,请注意TLS 的规则和限制

于 2011-05-16T17:59:32.760 回答
4

C++11 指定了一种thread_local存储类型,直接使用即可。

AnotherClass::threadSpecificAction()
{
  thread_local MyClass *instance = new MyClass();
  instance->doSomething();
}

一种可选的优化是也在线程本地存储上分配。

于 2015-11-23T14:41:14.340 回答
3

在 Windows 上,您可以使用TlsAllocTlsFree在线程本地存储中分配存储。

要使用 TLS 设置和检索值,可以分别使用TlsSetValueTlsGetValue

在这里,您可以看到一个有关如何使用它的示例。

于 2011-05-16T18:04:16.940 回答
2

只是附带说明... 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。

于 2014-11-01T03:09:11.740 回答
1

Folly(Facebook 开源库)具有 Thread Local Storage 的可移植实现。

据其作者称:

改进了非平凡类型的线程本地存储(与速度相似 pthread_getspecific但仅消耗单个pthread_key_t,并且比 快 4 倍boost::thread_specific_ptr)。

如果您正在寻找本地存储线程的可移植实现,这个库是一个不错的选择。

于 2016-06-22T15:35:15.933 回答