Sincronização & Compartilhamento

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);

Maiores detalhes

rdmd playground.d