共用方式為


執行緒

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)