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