O armazenamento local do thread é estático, mas se comporta de maneira bem diferente do armazenamento estático simples.
Quando você declara uma variável estática, há exatamente uma instância da variável. O sistema de compilador / tempo de execução garante que ele será inicializado para você algum tempo antes de realmente usá-lo, sem especificar exatamente quando (alguns detalhes omitidos aqui).
O C ++ 11 garante que essa inicialização será thread-safe; no entanto, antes do C ++ 11, essa segurança de thread não era garantida. Por exemplo
static X * pointer = new X;
poderia vazar instâncias de X se mais de um thread atingir o código de inicialização estática ao mesmo tempo.
Quando você declara um segmento de variável local, existem potencialmente muitas instâncias da variável. Você pode pensar neles como se estivessem em um mapa indexado por thread-id. Isso significa que cada thread vê sua própria cópia da variável.
Mais uma vez, se a variável for inicializada, o sistema compilador / runtime garante que essa inicialização acontecerá antes que os dados sejam usados e que a inicialização acontecerá para cada thread que usar a variável. O compilador também garante que a iniciação será thread-safe.
As garantias de segurança de thread significam que pode haver um pouco de código nos bastidores para fazer a variável se comportar da maneira que você espera - especialmente considerando que o compilador não tem como saber com antecedência exatamente quantos threads existem em seu programa e quantos deles tocarão na variável local do thread.
thread_local
variável local não faz sentido para começar ... cada thread tem sua própria pilha de chamadas.