Являются ли локальные переменные потока C++11 автоматически статическими?


есть ли разница между этими двумя сегментами кода:

void f() {
    thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

и

void f() {
    static thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

Предыстория: первоначально у меня был статический вектор V (для удержания некоторых промежуточных значений он очищается каждый раз, когда я ввожу функцию) и однопоточная программа. Я хочу превратить программу в многопоточную, поэтому как-то мне нужно избавиться от этого статического модификатора. Моя идея-превратить каждую статику в thread_local и не беспокоиться ни о чем другом? Может ли это приближается ответный огонь?

4 60

4 ответа:

согласно стандарту C++

когда thread_local применяется к переменной области блока storage-class-specifier static подразумевается если он не появляется явно

значит, это определение

void f() {
    thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

эквивалентно

void f() {
    static thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

однако статической переменной является не то же самое, что и переменная thread_local.

1 все переменные, объявленные с ключевым словом thread_local есть поток продолжительность хранения. Хранение этих объектов должно длиться в течение длительность потока, в котором они создаются. Существует четкое объект или ссылка на поток, и использование объявленного имени ссылается на сущность, связанная с текущим потоком

для различения этих переменных стандарт вводит новый термин поток длительность хранения вместе со статическим хранением продолжительность.

да, " локальное хранилище потоков "очень похоже на" глобальное "(или" статическое хранилище"), только вместо" длительность всей программы "у вас есть"длительность всего потока". Таким образом, переменная block-local thread-local инициализируется при первом прохождении элемента управления через его объявление, но отдельно в каждом потоке, и она уничтожается, когда поток заканчивается.

при использовании thread_local,static подразумевается в блочной области (см. ответ @Vlad), требуемой для члена класса; я думаю, означает связь для области пространства имен.

за 9.2 / 6:

в определении класса, член не должен объявляться с помощью спецификатора класса хранения thread_local, если только он также не объявлен static

чтобы ответить на исходный вопрос:

являются ли переменные C++11 thread_local автоматически статика?

нет выбора, кроме пространства переменных.

есть ли разница между этими двумя сегментами кода:

нет.

локальное хранилище потоков статично, но оно ведет себя совсем иначе, чем простое статическое хранилище.

при объявлении переменной static существует ровно один экземпляр переменной. Компилятор / система выполнения гарантирует, что он будет инициализирован для вас когда-нибудь, прежде чем вы его фактически используете, не указывая точно, когда (некоторые детали опущены здесь.)

C++11 гарантирует, что эта инициализация будет потокобезопасной, однако перед C++11 этот поток безопасность не гарантировалась. Например

static X * pointer = new X;

может произойти утечка экземпляров X, если одновременно несколько потоков попали в код статической инициализации.

когда вы объявляете переменный поток локальным, потенциально существует много экземпляров переменной. Вы можете думать о них как о карте, которая была индексирована thread-id. Это означает, что каждый поток видит свою собственную копию переменной.

еще раз, если переменная инициализирована компилятор / система выполнения гарантирует, что эта инициализация произойдет до использования данных и что инициализация произойдет для каждого потока, который использует переменную. Компилятор также гарантирует, что инициализация будет потокобезопасной.

гарантия безопасности потока означает, что может быть довольно много закулисного кода, чтобы заставить переменную вести себя так, как вы ожидаете, особенно учитывая, что компилятор не может заранее точно знать, как именно в вашей программе будет существовать много потоков, и сколько из них будет касаться локальной переменной потока.