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 Peterson, de Gary L. Peterson.
La version de base de cet algorithme (présentée ici) permet la synchronisation de deux unités d'exécution (threads, processus) partageant 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. Celle présentée par la présente est quant à elle une version généralisée à unités d'exécution.
Intuition générale : c'est une approche courtoise, où une unité d'exécution offre le passage aux autres, puis attend que l'une des autres lui rende la pareille ou qu'elles choisissent de ne pas accéder à cette section critique
Référez-vous pour l'essentiel à la version à deux unités d'exécution. La mécanique est similaire.
Cette version de l'algorithme de Peterson utilise deux états partagés, placés dans etats_synchro à droite :
Puisque cet algorithme fait correspondre les numéros d'unités de traitement et les numéros d'étapes, une valeur hors des bornes légales pour un numéro d'étape ( dans ce cas-ci) a été utilisé pour indiquer une étape non choisie. |
|
L'algorithme lui-même est implémenté par la fonction peterson_n(), à 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. Sa mécanique va comme suit :
|
|
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. |
|