對於局部變數,不同的線程每一次調用函數時都會在棧上得到該變數的一份新的拷貝,
全域的和靜態變數則只有一份實體,MFC提供了一種機制,使得可以像定義全域變數一樣定義
線程局部資料,所謂線程局部資料是指對於每一個訪問它們的線程都會有一份只屬於該線程的拷貝。
可使用宏THREAD_LOCAL(class_name, ident_name)定義線程局部資料,THREAD_LOCAL定義如下:
#define THREAD_LOCAL(class_name, ident_name) /
AFX_DATADEF CThreadLocal<class_name> ident_name;
其中AFX_DATADEF是個預留位置,class_name為線程局部資料的類型,ident_name為線程局部資料的名稱,
class_name必須派生於CNoTrackObject。
舉例:
struct CMyThreadData : public CNoTrackObject
{
CString strThread;
};
THREAD_LOCAL(CMyThreadData, threadData)
上面這行相當於
CThreadLocal<CMyThreadData> threadData;
定義了線程局部資料threadData,其實threadData依然是全域的,並不是真的的線程局部,但
它的所有成員都是貨真價實的線程局部資料,無論有多少個線程訪問threadData->strThread都會得到
一份只屬於自己的拷貝,這些拷貝其實是分配在堆中的,分配過程發生在每個線程首次訪問時。
CThreadLocal重載了operator->,每個線程首次訪問其成員時,它會new一個CMyThreadData出來放在堆上,那
CThreadLocal又是靠什麼記住堆上的哪個CMyThreadData是屬於哪個線程的呢?答案是TLS。
CThreadLocal派生於CThreadLocalObject,CThreadLocalObject有一個成員m_nSlot,
對於每一個由THREAD_LOCAL定義產生的CThreadLocalObject子物件,有獨一無二的值。