Synchronisation et partage

Même si la façon recommandée de faire du parallélisme en D est de se baser sur des données immutable et de synchroniser les threads avec le passage de messages, le langage supporte nativement des primitives de synchronisation et un attribut de type shared pour marquer les objets qui sont accessibles par plusieurs threads:

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

Par exemple, std.concurrency.send ne permet que d'envoyer des données immutable ou shared par passage de messages. shared est transitif, donc si une classe ou une structure est marquée comme shared, tous ses membres le seront aussi. Notez que les variables static ne sont pas shared par défaut parce qu'elles sont implémentées avec le stockage sur thread local (STL) et que chaque thread a une copie de la variable.

Les blocs synchronized permettent de demander au compilateur de créer une section critique où ne peut entrer qu'un seul thread à la fois.

synchronized
{
    importTruc();
}

Dans les méthodes de class, on peut associer plusieurs mutexs à ces blocs avec la syntaxe synchronized(membre1, membre2) pour réduire les risques de conflits. Le D insère automatiquement les sections critiques. Une classe complète peut être marquée comme synchronized et le compilateur s'assurera qu'un seul thread accède à une instance de la classe à la fois.

Des opérations atomiques peuvent être effectuées sur des variables shared en utilisant la fonction core.atomic.atomicOp:

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

Pour aller plus loin

rdmd playground.d