2011-09-30 79 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。