среды

Блок, относящийся только к системам Майкрософт

thread Модификатор расширенного класса хранилища используется для объявления локальной переменной потока. Для переносимого эквивалента в C++11 и более поздних версиях используйте описатель класса хранилища thread_local для переносимого кода. В Windows thread_local реализовано с __declspec(thread)помощью .

Синтаксис

__declspec(thread)declarator

Замечания

Локальное хранилище потока (TLS) — это механизм, с помощью которого в каждом потоке многопоточного процесса выделяется хранилище для хранения данных определенного потока. В стандартных многопоточных программах данные совместно используются всеми потоками заданного процесса, в то время как локальное хранилище потоков является механизмом предоставления данных для конкретного потока. Полное обсуждение потоков см. в разделе "Многопоточность".

Объявления локальных переменных потока должны использовать расширенный синтаксис атрибута и __declspec ключевое слово с thread ключевое слово. В следующем примере кода показано, как объявлять целочисленную локальную переменную потока и инициализировать её некоторым значением:

__declspec( thread ) int tls_i = 1;

При использовании локальных потоковых переменных в динамически загруженных библиотеках необходимо учитывать факторы, которые могут привести к неправильной инициализации локальной переменной потока:

  1. Если переменная инициализирована с помощью вызова функции (включая конструкторы), эта функция будет вызываться только для потока, вызвавшего загрузку двоичного или DLL-файла, и для этих потоков, запущенных после загрузки двоичного или DLL-файла. Функции инициализации не вызываются для любого другого потока, который уже выполнялся при загрузке библиотеки DLL. Динамическая инициализация происходит в вызове DllMain для DLL_THREAD_ATTACH, но библиотека DLL никогда не получает это сообщение, если библиотека DLL не в процессе при запуске потока.

  2. Локальные переменные потока, инициализированные статически с константными значениями, обычно инициализированы должным образом во всех потоках. Однако по состоянию на декабрь 2017 года в компиляторе Microsoft C++ возникает известная проблема соответствия, в которой constexpr переменные получают динамическую, а не статическую инициализацию.

    Примечание. Обе эти проблемы, как ожидается, будут исправлены в будущих обновлениях компилятора.

Кроме того, при объявлении локальных объектов и переменных потока необходимо соблюдать следующие рекомендации.

  • Атрибут можно применять thread только к объявлениям и определениям и объявлениям данных класса; thread нельзя использовать для объявлений или определений функций.

  • Атрибут можно указать только для элементов данных со статическим сроком thread хранения. К ним относятся глобальные объекты данных (как и ), локальные статические объекты, так static и externэлементы статических данных классов. Нельзя объявлять автоматические объекты данных с атрибутом 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++.

Завершение блока, относящегося только к системам Майкрософт

См. также

__declspec
Ключевые слова
Локальное хранилище потока (TLS)