分享方式:


thread

Microsoft 特定的

擴充 thread 儲存類別修飾詞是用來宣告執行緒區域變數。 針對 C++11 和更新版本中的可攜式對等專案,請使用 可攜式程式碼的thread_local 儲存類別規範。 在 Windows thread_local 上,會使用 實作 __declspec(thread)

語法

__declspec(thread)宣告子

備註

執行緒區域儲存區 (Thread Local Storage,TLS) 是一種機制,讓多執行緒處理序中的每個執行緒用來配置儲存區,以儲存執行緒特定資料。 在標準多執行緒程式中,資料是在特定處理序的所有執行緒之間共用,而執行緒區域儲存區則是用於配置每個執行緒資料的機制。 如需執行緒的完整討論,請參閱 多執行緒

執行緒區域變數的宣告必須使用 擴充屬性語法 __declspec 關鍵字搭配 thread 關鍵字。 例如,下列程式碼宣告整數執行緒區域變數,並使用值將它初始化:

__declspec( thread ) int tls_i = 1;

在動態載入的程式庫中使用執行緒區域變數時,您必須注意可能導致執行緒區域變數無法正確初始化的因素:

  1. 如果變數是使用函式呼叫初始化(包括建構函式),則只會針對導致二進位/DLL 載入進程的執行緒,以及載入二進位/DLL 之後啟動的執行緒呼叫此函式。 初始化函式不會針對載入 DLL 時已執行的任何其他執行緒呼叫。 動態初始化發生在DLL_THREAD_ATTACH的 DllMain 呼叫上,但如果執行緒啟動時 DLL 不在進程中,DLL 永遠不會取得該訊息。

  2. 以常數值以靜態方式初始化的執行緒區域變數通常會在所有線程上正確初始化。 不過,自 2017 年 12 月起,Microsoft C++ 編譯器中有已知的一致性問題,其中 constexpr 變數會收到動態而非靜態初始化。

    注意:這兩個問題預期會在編譯器的未來更新中修正。

此外,宣告執行緒區域物件和變數時,您必須觀察這些指導方針:

  • 您只能將 thread 屬性套用至類別和資料宣告和定義; thread 不能用於函數宣告或定義。

  • 您只能在具有靜態儲存持續時間的資料項目上指定 thread 屬性。 這包括全域資料物件(和 staticextern )、本機靜態物件,以及類別的靜態資料成員。 您無法使用 thread 屬性來宣告自動資料物件。

  • 您必須將 thread 屬性用於宣告和執行緒區域物件的定義,不論宣告和定義發生在相同的檔案還是個別的檔案中。

  • 您無法使用 thread 屬性做為類型修飾詞。

  • 由於允許使用 thread 屬性的物件宣告,這兩個範例在語意上是相等的:

    // declspec_thread_2.cpp
    // compile with: /LD
    __declspec( thread ) class B {
    public:
       int data;
    } BObject;   // BObject declared thread local.
    
    class B2 {
    public:
       int data;
    };
    __declspec( thread ) B2 BObject2;   // BObject2 declared thread local.
    
  • 標準 C 允許使用涉及本身參考的運算式來初始化物件或變數,但僅適用于非靜態物件。 雖然 C++ 通常允許具有參考本身之運算式之物件的這類動態初始化,但執行緒區域物件不允許這種初始化類型。 例如:

    // declspec_thread_3.cpp
    // compile with: /LD
    #define Thread __declspec( thread )
    int j = j;   // Okay in C++; C error
    Thread int tls_i = sizeof( tls_i );   // Okay in C and C++
    

    sizeof包含初始化物件的運算式不會構成本身的參考,而且在 C 和 C++ 中允許。

END Microsoft 特定的

另請參閱

__declspec
關鍵字
執行緒區域儲存區 (TLS)