wątek

Specyficzne dla firmy Microsoft

Rozszerzony thread modyfikator klasy magazynu służy do deklarowania zmiennej lokalnej wątku. W przypadku przenośnego odpowiednika w języku C++11 i nowszych użyj specyfikatora klasy magazynu thread_local dla przenośnego kodu. W systemie Windows thread_local jest implementowany za pomocą polecenia __declspec(thread).

Składnia

__declspec(thread)Declarator

Uwagi

Pamięć lokalna wątku (TLS) to mechanizm, za pomocą którego każdy wątek w procesie wielowątkowym przydziela pamięć dla danych specyficznych wątku. W standardowych programach wielowątkowych, dane są współużytkowane przez wszystkie wątki danego procesu, natomiast pamięć lokalna wątku jest mechanizmem przydzielania danych osobno dla danego wątku. Aby uzyskać pełną dyskusję na temat wątków, zobacz Multithreading (Wielowątkowość).

Deklaracje zmiennych lokalnych wątku muszą używać składni atrybutu rozszerzonego __declspec i słowa kluczowego thread ze słowem kluczowym. Na przykład, poniższy kod deklaruje lokalną zmienną całkowitą wątku i inicjuje ją wartością:

__declspec( thread ) int tls_i = 1;

W przypadku używania zmiennych lokalnych wątków w dynamicznie ładowanych bibliotekach należy pamiętać o czynnikach, które mogą spowodować nieprawidłowe zainicjowanie zmiennej wątkowej lokalnej:

  1. Jeśli zmienna zostanie zainicjowana za pomocą wywołania funkcji (w tym konstruktorów), ta funkcja zostanie wywołana tylko dla wątku, który spowodował załadowanie pliku binarnego/biblioteki DLL do procesu, oraz dla tych wątków, które rozpoczęły się po załadowaniu pliku binarnego/biblioteki DLL. Funkcje inicjowania nie są wywoływane dla żadnego innego wątku, który był już uruchomiony podczas ładowania biblioteki DLL. Inicjowanie dynamiczne występuje w wywołaniu dllMain dla DLL_THREAD_ATTACH, ale biblioteka DLL nigdy nie otrzymuje tego komunikatu, jeśli biblioteka DLL nie jest w procesie po uruchomieniu wątku.

  2. Zmienne lokalne wątku, które są inicjowane statycznie z wartościami stałymi, są zazwyczaj poprawnie inicjowane we wszystkich wątkach. Jednak od grudnia 2017 r. istnieje znany problem ze zgodnością w kompilatorze Microsoft C++, w którym constexpr zmienne otrzymują dynamiczne, a nie statyczne inicjowanie.

    Uwaga: Oba te problemy powinny zostać rozwiązane w przyszłych aktualizacjach kompilatora.

Ponadto należy przestrzegać tych wytycznych podczas deklarowania obiektów i zmiennych lokalnych wątku:

  • Atrybut można zastosować thread tylko do deklaracji i definicji klas i danych. thread Nie można ich używać w deklaracjach funkcji ani definicjach.

  • Atrybut można określić thread tylko dla elementów danych z czasem trwania magazynu statycznego. Obejmuje to globalne obiekty danych (zarówno static i extern), lokalne obiekty statyczne i statyczne składowe danych klas. Nie można zadeklarować automatycznych obiektów danych za pomocą atrybutu thread .

  • Należy użyć atrybutu thread dla deklaracji i definicji obiektu lokalnego wątku, niezależnie od tego, czy deklaracja i definicja występują w tym samym pliku, czy w oddzielnych plikach.

  • Nie można użyć atrybutu thread jako modyfikatora typu.

  • Ponieważ deklaracja obiektów używających atrybutu thread jest dozwolona, te dwa przykłady są semantycznie równoważne:

    // 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.
    
  • Standardowy C zezwala na inicjowanie obiektu lub zmiennej z wyrażeniem obejmującym odwołanie do samego siebie, ale tylko dla obiektów niestatycznych. Mimo że język C++ zwykle zezwala na takie dynamiczne inicjowanie obiektu z wyrażeniem obejmującym odwołanie do samego siebie, tego typu inicjowanie nie jest dozwolone w przypadku obiektów lokalnych wątku. Przykład:

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

    Wyrażenie sizeof zawierające inicjowany obiekt nie stanowi odwołania do samego siebie i jest dozwolone w językach C i C++.

END Microsoft Specific

Zobacz też

__declspec
Słowa kluczowe
Lokalny magazyn wątków (TLS)