Есть ли разница между этими двумя сегментами кода:
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 и не беспокоиться ни о чем другом? Может ли этот подход иметь неприятные последствия?
thread_local
Для начала нет смысла иметь локальную переменную… у каждого потока есть свой собственный стек вызовов.static
аstatic thread_local
не инициализирует один экземпляр переменной для каждого потока.static
vs,static thread_local
а скорее оauto
vsthread_local
, используя значение до C ++ 11auto
(т.е. автоматическое хранение).Ответы:
Согласно стандарту C ++
Значит, это определение
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.
Чтобы различать эти переменные, стандарт вводит новый термин « продолжительность хранения потока» наряду со статической продолжительностью хранения.
источник
static
и,extern
таким образом, не подразумевают класс хранения, а только связь для переменных thread_local даже во внутренних областях.Да, «локальное хранилище потока» очень похоже на «глобальное» (или «статическое хранилище»), только вместо «длительности всей программы» у вас есть «продолжительность всего потока». Таким образом, локальная переменная потока, локальная для блока, инициализируется при первом прохождении элемента управления через ее объявление, но отдельно в каждом потоке, и уничтожается, когда поток завершается.
источник
При использовании с
thread_local
,static
подразумевается в области видимости блока (см. Ответ @ Vlad), требуется для члена класса; Я думаю, это означает привязку к области пространства имен.По 9.2 / 6:
Чтобы ответить на исходный вопрос:
Нет выбора, кроме переменных области пространства имен.
Нет.
источник
Локальное хранилище потоков статично, но ведет себя совсем не так, как простое статическое хранилище.
Когда вы объявляете переменную статической, существует ровно один экземпляр переменной. Система компилятора / времени выполнения гарантирует, что он будет инициализирован для вас когда-нибудь до того, как вы его действительно начнете использовать, без указания точного времени (некоторые детали здесь опущены).
C ++ 11 гарантирует, что эта инициализация будет потокобезопасной, однако до C ++ 11 эта безопасность потока не была гарантирована. Например
static X * pointer = new X;
может привести к утечке экземпляров X, если несколько потоков одновременно попадут в код статической инициализации.
Когда вы объявляете переменный поток локальным, потенциально существует много экземпляров переменной. Вы можете думать о них как о карте, индексированной идентификатором потока. Это означает, что каждый поток видит свою копию переменной.
Еще раз, если переменная инициализируется, компилятор / система времени выполнения гарантирует, что эта инициализация произойдет до использования данных и что инициализация произойдет для каждого потока, который использует переменную. Компилятор также гарантирует, что запуск будет потокобезопасным.
Гарантии безопасности потоков означает, что может быть довольно много скрытого кода, чтобы переменная вела себя так, как вы ожидаете, особенно с учетом того, что компилятор не имеет возможности заранее узнать, сколько потоков будет существуют в вашей программе, и сколько из них коснется локальной переменной потока.
источник