Sincronización y uso compartido

Aunque el método preferido en D para usar multihilo es apoyarse en datos inmutables (mediante la palabra reservada immutable) y sincronizar hilos mediante paso de mensajes, el lenguaje soporta de forma nativa primitivas de sincronización así como elementos que sirven para marcar objetos como compartidos a los que se puede acceder desde múltiples hilos.

La palabra reservada shared sirve para indicar que una variable va a ser compartida entre múltiples hilos de ejecución diferentes:

shared(int)* p = new int;
int* t = p; // ERROR

Por ejemplo, la función std.concurrency.send sólo permite enviar datos marcados o con immutable o con shared, copiando el mensaje que se va a enviar. La palabra reservada shared es transitiva, es decir, si una clase o un estructura se marcan con shared, todos sus miembros serán marcados de la misma forma. Hay que tener en cuenta que las variables estáticas (con static) no se comparten (con shared) de forma predeterminada ya que la implementación usa TLS (Thread Local Storage en inglés) y cada hilo de ejecución tiene su propia copia.

Los bloques marcados con la palabra reservada synchronized le indican al compilador que dicho bloque es una sección crítica y que sólo un hilo de ejecución puede acceder a ella al mismo tiempo.

synchronized {
    importStuff();
}

Dentro de las funciones miembro de clases, estos bloques se pueden limitar a objetos con exclusión mutua (mutexes en inglés) mediante synchronized(member1, member2) con el fin de reducir la contención. El compilador de D inserta las secciones críticas de forma automática. Además, se puede marcar una clase completa con synchronized, con lo que el compilador se asegurará de que sólo un hilo de ejecución al mismo tiempo tenga acceso a una instancia concreta de dicha clase.

Se pueden usar operaciones atómicas en variables marcadas como shared mediante la función core.atomic.atomicOp:

shared int test = 5;
test.atomicOp!"+="(4);

En profundidad

rdmd playground.d