如何分配线程本地存储?

Wil*_*mKF 57 c++ linux multithreading new-operator thread-local-storage

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

如何为我的C++类分配内存,以便每个线程都有自己的类实例副本?

AnotherClass::threadSpecificAction()
{
  // How to allocate this with thread local storage?
  static MyClass *instance = new MyClass();

  instance->doSomething();
}
Run Code Online (Sandbox Code Playgroud)

这是在Linux上.我没有使用C++ 0x,这是gcc v3.4.6.

rav*_*int 69

#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();
Run Code Online (Sandbox Code Playgroud)

  • @entheh:超级懒惰是指那些重视构造良好的示例代码的人吗?=). (15认同)
  • 这个.不要打扰特定于操作系统的东西,`boost :: thread_specific_ptr`是干净,可移植和惯用的. (10认同)
  • 最初的问题是关于"静态"线程本地,这正是通过`thread_local`关键字在C++中构建的,因此他应该像C++的本地支持一样使用`thread_local MyClass实例;`.此答案中的`thread_specific_ptr`代码更复杂,符合标准.虽然这里不是正确的选择,但`thread_specific_ptr`对_dynamically_分配线程本地对象仍然有用. (4认同)
  • 对于超级懒惰:`#include <boost/thread/tss.hpp>` (2认同)

Deq*_*ing 64

值得注意的是,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;
}
Run Code Online (Sandbox Code Playgroud)

可能的输出:

Rage counter for a: 2
Rage counter for main: 2
Rage counter for b: 2
Run Code Online (Sandbox Code Playgroud)

  • @reavenisadesk,`mutex`只是同步输出,因为流不会立即写入所有内容.如果没有锁定,你会读到类似"愤怒计数器的愤怒计数器:aRage计数器:主要"...... (4认同)
  • GCC在4.8中增加了对"thread_local"的支持.如果您使用的是4.7或更早版本,则需要使用`__thread`来指定存储类. (2认同)

小智 14

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

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

所以你的实例变量看起来像:

static __thread MyClass *instance = new MyClass();
Run Code Online (Sandbox Code Playgroud)

  • 当使用__thread时,要注意析构函数没有在MyClass上执行.(boost :: thread_specific_ptr <MyClass>或thread_local MyClass执行析构函数.) (2认同)

Jas*_*son 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();
}
Run Code Online (Sandbox Code Playgroud)