Existe uma diferença entre esses dois segmentos de código:
void f() {
thread_local vector<int> V;
V.clear();
... // use V as a temporary variable
}
e
void f() {
static thread_local vector<int> V;
V.clear();
... // use V as a temporary variable
}
História de fundo: originalmente eu tinha um vetor ESTÁTICO V (para manter alguns valores intermediários, ele é limpo toda vez que eu entro na função) e um programa de thread único. Quero transformar o programa em um multithreading, então de alguma forma tenho que me livrar desse modificador estático. Minha ideia é transformar cada estático em thread_local e não se preocupar com mais nada? Essa abordagem pode sair pela culatra?
thread_local
variável local não faz sentido para começar ... cada thread tem sua própria pilha de chamadas.static
vez destatic thread_local
não inicializar uma instância da variável para cada thread.static
vs,static thread_local
mas sim sobreauto
vsthread_local
, usando o significado pré-C ++ 11 deauto
(isto é, armazenamento automático).Respostas:
De acordo com o padrão C ++
Então, isso significa que esta definição
void f() { thread_local vector<int> V; V.clear(); ... // use V as a temporary variable }
é equivalente a
void f() { static thread_local vector<int> V; V.clear(); ... // use V as a temporary variable }
No entanto, uma variável estática não é o mesmo que uma variável thread_local.
Para distinguir essas variáveis, o padrão apresenta uma nova duração de armazenamento de thread de termo junto com a duração de armazenamento estático.
fonte
static
e,extern
portanto, não implica classe de armazenamento, mas apenas ligação para variáveis thread_local, mesmo em escopos internos.Sim, "armazenamento local de thread" é muito semelhante a "global" (ou "armazenamento estático"), mas ao invés de "duração de todo o programa" você tem "duração de todo o thread". Portanto, uma variável local do segmento de bloco local é inicializada na primeira vez que o controle passa por sua declaração, mas separadamente em cada segmento, e é destruída quando o segmento termina.
fonte
Quando usado com
thread_local
,static
está implícito no escopo do bloco (veja a resposta de @Vlad), exigido para um membro da classe; Eu acho que significa ligação para o escopo do namespace.Por 9.2 / 6:
Para responder à pergunta original:
Não há escolha, exceto para variáveis de escopo de namespace.
Não.
fonte
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.
fonte