L'article suppose que vous avez lu la présentation générale des algorithmes de synchronisation classiques, de même que Algos-Section-Critique-General.html qui explique la démarche d'ensemble, présente les risques et décrit les classes Producteur et Consommateur qui sont réinvesties ici.
Le code qui suit est une implémentation de l'algorithme de Dekker, qu'on attribue au mathématicien néerlandais Theodorus Dekker. Cet algorithme permet la synchronisation de deux unités d'exécution (threads, processus) partageant une zone de mémoire, sans avoir recours à des outils de synchronisation comme ceux que l'on trouve dans les systèmes d'exploitation contemporains. Ce serait le premier algorithme du genre, historiquement.
Intuition générale : chaque unité d'exécution annonce son intention d'entrer dans la section critique. Si une situation ambiguë survient, un système de tour donne à l'une des unités d'exécution priorité sur l'autre
Le principe de cet algorithme va comme suit :
L'algorithme de Dekker utilise deux états partagés, placés dans etats_synchro à droite :
Remarquez le recours à des assertions dynamiques pour valider les indices. Déboguer un algorithme parallèle peut être complexe et ardu; ne négligez pas ces précieux outils! L'algorithme demande occasionnellement de connaître l'identité de l'autre unité d'exécution. Ce service est statique (offert directement par la classe). L'algorithme demande aussi de passer d'un tour à l'autre, logique cyclique qu'implémente le service prochain_tour(). Cet algorithme a sans doute inspiré (au moins en partie) l'algorithme de Peterson. |
|
L'algorithme de Dekker est implémenté par la fonction dekker(), à droite, exécutée dans un thread distinct. Le code clé de cet algorithme est celui qui gère l'entrée dans la section jugée critique, de même que celui qui en gère la sortie. En gros :
La mécanique de la répétitive d'entrée dans la zone critique fait en sorte qu'il arrive assez fréquemment que les circonstances mènent une même unité de traitement accède à la zone critique plusieurs fois consécutives. C'est la vie. |
|
Sans grande surprise, le programme principal lance les diverses unités de traitement souhaitées, assure leur identification correcte et leur supplée le booléen qu'elles partageront et qui jouera pour elles le rôle d'un signal de fin, puis attend la fin des threads et nettoie les ressources attribuées au préalable. |
|