Локальное хранилище потоков статично, но ведет себя совсем не так, как простое статическое хранилище.
Когда вы объявляете переменную статической, существует ровно один экземпляр переменной. Система компилятора / времени выполнения гарантирует, что он будет инициализирован для вас когда-нибудь до того, как вы его действительно начнете использовать, без указания точного времени (некоторые детали здесь опущены).
C ++ 11 гарантирует, что эта инициализация будет потокобезопасной, однако до C ++ 11 эта безопасность потока не была гарантирована. Например
static X * pointer = new X;
может привести к утечке экземпляров X, если несколько потоков одновременно попадут в код статической инициализации.
Когда вы объявляете переменный поток локальным, потенциально существует много экземпляров переменной. Вы можете думать о них как о карте, индексированной идентификатором потока. Это означает, что каждый поток видит свою копию переменной.
Еще раз, если переменная инициализируется, компилятор / система времени выполнения гарантирует, что эта инициализация произойдет до использования данных и что инициализация произойдет для каждого потока, который использует переменную. Компилятор также гарантирует, что запуск будет потокобезопасным.
Гарантии безопасности потоков означает, что может быть довольно много скрытого кода, чтобы переменная вела себя так, как вы ожидаете, особенно с учетом того, что компилятор не имеет возможности заранее узнать, сколько потоков будет существуют в вашей программе, и сколько из них коснется локальной переменной потока.
thread_local
Для начала нет смысла иметь локальную переменную… у каждого потока есть свой собственный стек вызовов.