回答
請仔細閱讀Wikipedia entry。
線程本地存儲並不是C++特有的東西。有時候會有不同的名稱,比如「TLS」(只是線程本地存儲的縮寫)或「線程專用存儲」(TSS)。
大多數操作系統都提供API來訪問每線程存儲。例如,Windows有一個以「TLS」開頭的bunch of API functions。在底層,Win32爲各種線程數據保留了一個特殊區域,包括用戶線程本地存儲,可通過特定CPU寄存器(x86上的FS)訪問。 Linux通過pthread API提供線程特定的存儲,其名稱如pthread_key_create,這些通常使用類似的技術實現。
操作系統可能根本不提供任何支持。但是,如果操作系統通過API提供了一個獨立於進程的線程ID,那麼C++運行時庫可以在內部維護一些概念上的內容,如std::map<thread_id, per_thread_storage>
。當然,那麼per_thread_storage
是什麼問題。如果一個程序是靜態鏈接的,它可能就像是一個指向一個大型結構的指針,所有的線程局部存儲變量都在程序中聲明爲元素。這是一個過分簡單化,但你得到的一般想法。
訪問線程本地存儲變量顯然不僅僅是一個直接的內存讀取或寫入。這可能比這更有意義。如果你打算在一個特定的函數中使用線程本地/特定存儲,我建議你先將線程本地存儲指針複製到一個局部變量中。
全局變量(或可寫靜態數據 - WSD)通常存儲在獨立於堆棧,堆和代碼的內存塊中。在可執行文件的代碼開始運行之前,會創建並初始化WSD塊。
C++ 0x引入了thread_local
關鍵字,它確保每個線程創建一個單獨的全局變量實例。問題是每個線程需要加載一個不同的塊。
下一個難點是變量的地址在鏈接時不固定,並且對於每個線程都不相同。
圍繞此問題有兩種方法。一種是讓編譯器生成一個函數調用以獲得正確的塊,而另一種是更改ABI以將TLS塊存儲在其中一個處理器寄存器中。然後可以使用偏移來訪問正確的thread_local
變量。
這與操作系統存儲單個void*
值的庫支持不同,該值可用於存儲指向已在進程堆上分配的線程本地塊的指針。
如果你想血淋淋的細節看here。
您可以使用boost::thread在不同平臺上可移植地處理TLS。每個代碼的實現都在代碼中,並且可以幫助您瞭解不同的系統如何處理這個區域。
在C++ 0x中,編譯器確實支持使用thread_local關鍵字的TLS – doron 2010-09-17 11:22:36
使用boost很好,但是爲了記錄,一些編譯器確實已經購買了問題空間。 http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Thread-Local.html – 2010-09-17 11:23:33
你說得對,我會更新它。 – 2010-09-17 11:32:29
- 1. 線程本地存儲GCC編譯器
- 2. 像compilr.com實現C#編譯器(在線)
- 3. Lua,實現線程本地存儲可訪問C API
- 4. C++ 0x線程
- 5. C++編譯器如何在內存中實現虛擬繼承?
- 6. 如何從C#編譯存儲過程?
- 7. 如何打開英特爾C++編譯器的C++ 0x 12.1.2
- 8. 線程本地存儲C#類庫
- 9. 爲AVR編譯C++ 0x
- 10. C++ 0x TMP編譯速度
- 11. C++ 0x優化編譯器質量
- 12. 本地網絡的在線c/C++編譯器
- 13. 線程本地存儲(TLS) - 編譯器錯誤
- 14. 如何在C++中編譯編譯器?
- 15. C++ 0x的任何實現在那裏?
- 16. 建立在C++ 0x線程標準上的Actor實現
- 17. C++在任何編譯器中的0x庫可用性?
- 18. 編譯的C程序存儲器地址
- 19. 編譯本地C++
- 20. 在C++ 0x多線程中等待
- 21. 如何在C中編譯C程序?
- 22. C++ 0x線程問題
- 23. 如何爲iPhone和iPhone模擬器編譯C++ 0x代碼
- 24. 如何在動態加載的DLL中正確實現(C++)線程本地存儲?
- 25. C++編譯器實現命名空間
- 26. 實現C++概念的編譯器
- 27. 升壓1.53本地日期時間編譯器錯誤與-std =的C++ 0x
- 28. 使用scons編譯器編譯C++
- 29. 本地存儲實現
- 30. 使用__declspec(線程)的線程本地存儲在C++/CLI中失敗
C++標準具有零(或非常少)的實現細節。 – 2010-09-17 15:49:23
現在可以幫助:http://www.akkadia.org/drepper/tls.pdf – 2013-01-18 08:42:54