Em D, a maneira preferida de fazer multi-threading
é confiar em dados immutable
e sincronizar as threads
usando a troca de mensagens. No entanto, a linguagem
tem suporte a primitivas de sincronização, bem como
suporte ao sistema de tipos com shared
para marcar objetos
que são acessados de várias threads.
Use o identificador de tipo shared
para marcar variáveis
que são compartilhadas entre diferentes threads:
shared(int)* p = new int;
int* t = p; // ERRO
Por exemplo, o std.concurrency.send
só permite o envio de
dados immutable
ou shared
e copiar a mensagem
a ser enviada. O shared
é transitivo, portanto, se uma class
ou struct
for marcado como shared
, todos os seus membros também serão.
Observe que as variáveis static
não são shared
por
padrão porque são implementadas usando
thread local storage (TLS) e cada thread recebe
sua própria variável.
Os blocos synchronized
são usados para informar ao compilador
para criar uma seção crítica que só pode ser acessada
por uma thread de cada vez. Sem argumentos, um mutex exclusivo
para essa instrução será bloqueado e desbloqueado.
synchronized {
importStuff();
}
A sincronização pode ser limitada somente a um objeto da classe
mutex, passando o objeto como um argumento usando
synchronized (obj)
para reduzir a contenção.
O compilador D insere seções críticas automaticamente.
Uma classe inteira pode ser marcada
como synchronized
e, nesse caso, o compilador
garante que apenas uma thread acesse uma instância
concreta de cada vez.
As operações atômicas em variáveis shared
podem ser
executadas usando o operador auxiliar core.atomic.atomicOp
:
shared int test = 5;
test.atomicOp!"+="(4);