c++ linux multithreading new-operator thread-local-storage

c++ - ¿Cómo asignar el almacenamiento local de hilo?



linux multithreading (9)

Tengo una variable en mi función que es estática, pero me gustaría que sea estática por hilo.

¿Cómo puedo asignar la memoria para mi clase de C ++ de modo que cada hilo tenga su propia copia de la instancia de la clase?

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

Esto está en Linux. No estoy usando C ++ 0x y esto es gcc v3.4.6.


C ++ 11 especifica un tipo de almacenamiento thread_local , solo thread_local .

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

Una optimización opcional es asignar también en el almacenamiento local de subprocesos.


En Windows, puede usar TlsAlloc y TlsFree para asignar almacenamiento en los hilos de almacenamiento local.

Para establecer y recuperar valores con TLS, puede usar TlsSetValue y TlsGetValue , respectivamente

example puede ver un ejemplo de cómo se usaría.



Si está utilizando Pthreads puede hacer lo siguiente:

//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(); }


Solo una nota al margen ... MSVC ++ admite declspec (hilo) de VSC ++ 2005

#if (_MSC_VER >= 1400) #ifndef thread_local #define thread_local __declspec(thread) #endif #endif

El problema principal es (que se resuelve en boost :: thread_specific_ptr) las variables marcadas con él no pueden contener ctor o dtor.


Vale la pena señalar que C ++ 11 introduce la palabra clave thread_local .

Aquí hay un ejemplo de especificadores de duración de almacenamiento :

#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; }

Posible resultado:

Rage counter for a: 2 Rage counter for main: 2 Rage counter for b: 2


boost::thread_specific_ptr es la mejor manera de solución portátil.

En Linux & GCC puedes usar __thread modifier .

Entonces su variable de instancia se verá así:

static __thread MyClass *instance = new MyClass();


Folly (Facebook Open-source Library) tiene una implementación portátil de Thread Local Storage.

Según sus autores:

Se mejoró el almacenamiento local de subprocesos para tipos no triviales (velocidad similar a pthread_getspecific pero solo consume una sola pthread_key_t , y 4 veces más rápido que boost::thread_specific_ptr ).

Si busca una implementación portátil de Local Storage Thread, esta biblioteca es una buena opción.


#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();