2011-09-30 83 views
19

如何定义不在不同线程之间共享的局部静态变量(保持函数调用之间的值)?如何定义线程局部本地静态变量?

我要找无论是在C和C++

+0

你在使用什么操作系统? TLS在unixen和windows之间不可移植。 – bdonlan

+3

C++ 11引入了另一个称为['thread_local']的存储持续时间(http://en.cppreference.com/w/cpp/language/storage_duration)。尝试使用它。 – Nawaz

+0

操作系统是Windows ... –

回答

9

TlsAlloc()/TlsSetValue()/ TlsGetValue()

在Windows

使用编译器的内部:在Linux(其他POSIX使用_declspec(thread)

? ??):get_thread_area()和相关的

+0

在MSDN上阅读后,Tls函数正是我所期待的。 –

+2

你忘了TlsFree :-) –

2

当前的C标准的螺纹或类似的模型没有一个答案,所以你无法得到答案,在那里。

POSIX预见的效用是pthread_[gs]etspecific

C标准的下一个版本增加了线程,并具有线程本地存储的概念

-3

您可以为每个线程创建从堆中分配的数据结构。

示例:在Windows上使用Windows API

struct ThreadLocal 
{ 
    int var1; 
    float var2; 
    //etc.. 
} 
8

只需在你的函数中使用static和__thread。

例子:

int test(void) 
{ 
     static __thread a; 

     return a++; 
} 
+3

是__thread标准吗? –

+2

@Ali:不,它是由GCC和其他一些编译器提供的扩展。在MSVC上,我认为你应该使用'__declspec(thread)'。 –

+3

__thread适用于linux,bsd,aix,以及xl_c,gcc和许多其他编译器。它可以平凡#defined到__declspec(线程)在Windows上。 –

1

你可以让自己的线程特定的本地存储为每个线程ID单。类似这样的:

struct ThreadLocalStorage 
{ 
    ThreadLocalStorage() 
    { 
     // initialization here 
    } 
    int my_static_variable_1; 
    // more variables 
}; 

class StorageManager 
{ 
    std::map<int, ThreadLocalStorage *> m_storages; 

    ~StorageManager() 
    { // storage cleanup 
     std::map<int, ThreadLocalStorage *>::iterator it; 
     for(it = m_storages.begin(); it != m_storages.end(); ++it) 
      delete it->second; 
    } 

    ThreadLocalStorage * getStorage() 
    { 
     int thread_id = GetThreadId(); 
     if(m_storages.find(thread_id) == m_storages.end()) 
     { 
      m_storages[thread_id] = new ThreadLocalStorage; 
     } 

     return m_storages[thread_id]; 
    } 

public: 
    static ThreadLocalStorage * threadLocalStorage() 
    { 
     static StorageManager instance; 
     return instance.getStorage(); 
    } 
}; 

GetThreadId();是用于确定调用者的线程ID的平台特定功能。事情是这样的:现在

int GetThreadId() 
{ 
    int id; 
#ifdef linux 
    id = (int)gettid(); 
#else // windows 
    id = (int)GetCurrentThreadId(); 
#endif 
    return id; 
} 

,线程函数中,你可以使用它的本地存储:

void threadFunction(void*) 
{ 
    StorageManager::threadLocalStorage()->my_static_variable_1 = 5; //every thread will have 
                  // his own instance of local storage. 
} 
+0

您还需要同步(例如读/写互斥)来保护'm_storages'免受多线程访问。当然是 –

+0

。你是对的。 – GreenScape

+0

不仅是m_storages,还有std :: map和本地“静态StorageManager实例”不是线程安全的。 在本地代码中实现高效单例并不是一件容易的事情,请参阅Scott Meyers和Andrei Alexandrescu的“C++和双重检查锁定的危险”。 http://erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf – zhaorufei

2

您也可以使用C++ 11线程本地存储的添加,如果你有机会到C++ 11。