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.
On le nomme parfois aussi algorithme de la boulangerie, ou encore simplement algorithme de Lamport, mais l'ami Lamport a plusieurs algorithmes connus à son actif alors...
Le code qui suit est une implémentation de l'algorithme du boulanger, de Leslie Lamport. Cet algorithme permet la synchronisation de 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. Il repose sur un ingénieux système de votation.
Intuition générale : on cherche à atteindre un consensus en procédant à un vote, tenant compte d'un identifiant unique à chaque unité d'exécution. Ceci permet de créer un ordonnancement pour départager des situations qui seraient, autrement, ambiguës.
Le principe de cet algorithme va comme suit :
L'algorithme du boulanger utilise deux états partagés, placés dans etats_synchro à droite :
Le service lock() permet d'accéder à la section critique. Sa mécanique va comme suit :
Quitter la zone critique implique remettre le vote à zéro, tout simplement, ce qui assurera un bon redémarrage lors de la prochaine votation. |
|
L'algorithme du boulanger est implémenté par la fonction lamport(), à 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. L'une des grandes vertus de cet algorithme est qu'en surface, il a le comportement attendu des verrous avec lesquels nous sommes plus familiers aujourd'hui. En effet, même dans la terminologie, nous pouvons voir poindre ce qui deviendra éventuellement le mutex que nous connaissons bien. |
|
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. |
|