Segurança entre threads

ParseInput

A sobrecarga 1 de ParseInput (todos os parâmetros explícitos) é totalmente segura entre threads. Cada chamada opera inteiramente na sua própria pilha e nas suas próprias variáveis locais; não é lido nem gravado qualquer estado partilhado. Pode ser chamada em simultâneo a partir de qualquer número de threads sem necessidade de sincronização.

// É seguro chamar a partir de múltiplas threads simultaneamente.
R := ParseInput(Input, itDate, '~', [], sopEqual, sqlMySQL);

As sobrecargas 2–5 lêem a variável global GDefaultDialect no momento da chamada. São seguras para utilização a partir de múltiplas threads, desde que SetSQLDialect nunca seja chamada após o início do processamento multithread. O padrão típico de segurança consiste em chamar SetSQLDialect uma vez durante o arranque da aplicação — antes da criação de quaisquer threads secundárias — e, em seguida, utilizar as sobrecargas 2–5 livremente a partir de qualquer thread:

// Thread principal, arranque da aplicação.
SetSQLDialect(sqlElevateDB);

// Threads de trabalho: seguras, porque `SetSQLDialect` nunca mais é chamado.
R := ParseInput(Input, itDate);

Se o dialecto tiver de ser alterado em tempo de execução enquanto as threads estão a funcionar, utilize exclusivamente a sobrecarga 1 e passe o dialecto explicitamente em cada chamada.

Componente TEgStrParser

Instâncias diferentes

Chamadas simultâneas a Parse() em instâncias diferentes de TEgStrParser são seguras para threads. Cada instância armazena o seu próprio FSqlDialect e passa-o diretamente para a sobrecarga 1 de ParseInput. Nenhuma variável global é lida ou gravada.

// Seguro: Parser1 e Parser2 são instâncias distintas.
// Thread A:
R := Parser1.Parse(Input1, itDate);
// Thread B (simultaneamente):
R := Parser2.Parse(Input2, itInteger);

A mesma instância

As chamadas simultâneas à mesma instância de TEgStrParser não são seguras para threads. FLastResult e FLastControl são gravados em cada chamada sem sincronização; as gravações simultâneas produzem uma corrida de dados.

Se um único componente tiver de ser partilhado entre threads, proteja cada chamada com um bloqueio:

// Um bloqueio por instância de componente partilhada.
FCritSect.Enter;
try
  R := Parser1.Parse(Input, itDate);
finally
  FCritSect.Leave;
end;

Em alternativa, crie uma instância separada de TEgStrParser por thread, ou utilize diretamente a sobrecarga 1 de ParseInput nas threads de trabalho e reserve o componente para a thread principal.

SetSQLDialect / GetSQLDialect

SetSQLDialect e GetSQLDialect acedem à variável global GDefaultDialect sem sincronização. Não chame nenhuma destas funções a partir de uma thread enquanto outra thread possa estar a chamar as sobrecargas 2–5 de ParseInput ou o outro acessador de dialeto.

// Inseguro: o dialeto pode alterar-se enquanto a thread de trabalho o lê.
// Thread de trabalho:
R := ParseInput(Input, itDate);   // lê GDefaultDialect
// Thread principal (simultaneamente):
SetSQLDialect(sqlMySQL); // escreve em GDefaultDialect

FormatSettings

ParseInputFormatSettings (as definições globais de localização do Delphi) para inicializar os registos SqlFmt e LocaleFmt por cada chamada. No Delphi 11 e versões posteriores, FormatSettings é, por predefinição, uma variável local da thread quando {$DEFINE POSIX} está definido ou quando o RTL está configurado para segurança de threads. No Windows, com as definições predefinidas do RTL, FormatSettings é uma variável global; alterá-la a partir de uma thread enquanto outra está a chamar ParseInput constitui uma corrida de dados.

Na prática, FormatSettings é normalmente definida uma vez no arranque e não é alterada posteriormente, o que é seguro. Se forem necessárias substituições de localização por thread, utilize diretamente as sobrecargas das funções RTL baseadas em TFormatSettings, em vez de modificar a variável global.

Resumo

Cenário Seguro?
Sobrecarga 1 de ParseInput, múltiplas threads Sim
Sobrecargas 2–5 de ParseInput, múltiplas threads, SetSQLDialect chamado apenas no arranque Sim
Sobrecargas 2–5 de ParseInput, SetSQLDialect chamado em tempo de execução a partir de outra thread Não
TEgStrParser.Parse(), instâncias diferentes, múltiplas threads Sim
TEgStrParser.Parse(), mesma instância, múltiplas threads Não
SetSQLDialect / GetSQLDialect em simultâneo com as sobrecargas 2–5 Não
(C) 2026 Easygate, Lda