Freigeben über


Thread

Microsoft-spezifisch

Der erweiterte Speicherklassenmodifizierer thread wird verwendet, um eine threadlokale Variable zu deklarieren. Verwenden Sie für das portierbare Äquivalent in C++11 und höher den Speicherklassenbezeichner thread_local für portierbaren Code. Unter Windows wird thread_local mit __declspec(thread) implementiert.

Syntax

__declspec(thread)-Deklarator

Hinweise

Threadlokaler Speicher (TLS) ist der Mechanismus, mit dem jeder Thread in einem Multithreadprozess den Speicher für threadspezifische Daten zuordnet. In den standardmäßigen Multithreadprogrammen werden Daten auf allen Threads eines angegebenen Prozesses freigegeben, während der threadlokale Speicher der Mechanismus zum Zuordnen der threadspezifischen Daten ist. Eine detaillierte Erläuterung zu Threads finden Sie unter Multithreading.

Deklarationen von threadlokalen Variablen müssen eine erweiterte Attributsyntax und das Schlüsselwort __declspec mit dem Schlüsselwort thread verwenden. Mit folgendem Code wird z. B. eine Ganzzahl-TLS-Variable deklariert und mit einem Wert initialisiert:

__declspec( thread ) int tls_i = 1;

Wenn Sie threadlokale Variablen in dynamisch geladenen Bibliotheken verwenden, müssen Sie sich die Aspekte bewusst machen, die dazu führen können, dass eine threadlokale Variable nicht ordnungsgemäß initialisiert wird:

  1. Wenn die Variable mit einem Funktionsaufruf (einschließlich Konstruktoren) initialisiert wird, wird diese Funktion nur für den Thread aufgerufen, der dazu führte, dass die Binär-/DLL-Datei in den Prozess geladen wurde, sowie für die Threads, die nach dem Laden der Binär-/DLL-Datei gestartet wurden. Die Initialisierungsfunktionen werden nicht für einen anderen Thread aufgerufen, der beim Laden der DLL-Datei bereits ausgeführt wurde. Eine dynamische Initialisierung erfolgt im DllMain-Aufruf für DLL_THREAD_ATTACH. Die DLL-Datei erhält diese Nachricht aber nie, wenn die DLL-Datei nicht verarbeitet, wenn der Thread gestartet wird.

  2. Threadlokale Variablen, die statisch mit konstanten Werten initialisiert wurden, werden im Allgemeinen in allen Threads ordnungsgemäß initialisiert. Seit Dezember 2017 gibt es jedoch ein bekanntes Konformitätsproblem im Microsoft C++-Compiler, durch das für constexpr-Variablen eine dynamische anstelle einer statischen Initialisierung erfolgt.

    Hinweis: Beide Probleme werden voraussichtlich mit zukünftigen Updates des Compilers behoben.

Sie müssen diese Richtlinien auch beachten, wenn Sie threadlokale Objekte und Variablen deklarieren:

  • Sie können das thread-Attribut nur auf Klassen- und Datendeklarationen und -definitionen anwenden. thread kann nicht für Funktionsdeklarationen oder - definitionen verwendet werden.

  • Sie können das thread-Attribut nur für Datenelemente mit statischer Speicherdauer angeben. Hierzu zählen globale Datenobjekte (sowohl static als auch extern), lokale statische Objekte sowie statische Datenmember von Klassen. Sie können mit dem thread-Attribut keine automatischen Datenobjekte deklarieren.

  • Sie müssen das thread-Attribut für die Deklaration und Definition eines threadlokalen Objekts verwenden, unabhängig davon, ob die Deklaration und Definition in der gleichen Datei oder in separaten Dateien erfolgen.

  • Sie können das thread-Attribut nicht als Typmodifizierer verwenden.

  • Da die Deklaration von Objekten, die das thread-Attribut verwenden, zulässig ist, sind diese beiden Beispiele semantisch gleichwertig:

    // 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.
    
  • In Standard-C ist die Initialisierung eines Objekts oder einer Variable mit einem Ausdruck zulässig, der einen Verweis auf sich selbst enthält. Dies gilt jedoch nur für nicht statische Objekte. Auch wenn diese dynamische Objektinitialisierung mit einem Ausdruck, der einen Verweis auf sich selbst enthält, in C++ normalerweise als zulässig gilt, ist dieser Initialisierungstyp für threadlokale Objekte nicht zulässig. Zum Beispiel:

    // 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++
    

    Ein sizeof-Ausdruck, der das Objekt enthält, das derzeit initialisiert wird, stellt keinen Verweis auf sich selbst dar und ist sowohl in C als auch in C++ zulässig.

Ende Microsoft-spezifisch

Weitere Informationen

__declspec
Schlüsselwörter
Threadlokaler Speicher (TLS)