Synchronisation de Processus -
Moniteurs
Cours L3 – 2022/2023
1
Sémaphores
Erreurs de programmation courantes
Process i Process j Process k Process m
P(S) V(S) P(S) P(S)
CS CS CS if(something or other)
P(S) V(S) return;
CS
V(S)
Problèmes avec les sémaphores
Les sémaphores sont des primitives de très « bas niveau »
● Les utilisateurs peuvent facilement commettre de petites erreurs
● Similaire à la programmation en langage assembleur
● Une petite erreur met le système à l'arrêt
● Très difficile à déboguer
● De plus, nous semblons les utiliser de deux manières
● Pour l'exclusion mutuelle, l'abstraction « réelle » est une section
critique
● Mais l'exemple de tampon limité illustre quelque chose de
différent, où les processus « communiquent » à l'aide de
sémaphores
● Simplification : fournir la prise en charge de la concurrence
dans le compilateur : Moniteurs
Moniteur
Est un module contenant:
une ou plusieurs procédures
une séquence d’initialisation
variables locales
Caractéristiques:
variables locales accessibles seulement à l’aide d’une
procédure du moniteur
un processus entre dans le moniteur en invoquant une
de ses procédures
un seul processus peut exécuter dans le moniteur à
tout instant (mais plusieurs. processus peuvent être en attente dans le moniteur)
4
Moniteur
Il assure à lui seul l’exclusion mutuelle: pas besoin de le
programmer explicitement
On assure la protection des données partagées en les plaçant
dans le moniteur
Le moniteur verrouille les données partagées lorsqu’un
processus y entre
Synchronisation de processuss est effectuée en utilisant des
variables conditionnelles qui représentent des conditions
après lesquelles un processus pourrait attendre avant
d’exécuter dans le moniteur
5
Structure générale du moniteur (Hoare)
Monitor monitor_name For example:
{ Monitor stack
// shared variable declarations {
procedure P1(. . . .) { int top;
. . . . void push(any_t *) {
} . . . .
procedure P2(. . . .) { }
. . . . any_t * pop() {
} . . . .
. }
. initialization_code()
procedure PN(. . . .) { {
. . . . . . . .
} }
initialization_code(. . . .) { }
. . . .
}
}
La seule façon de manipuler les variables internes au moniteur est
d’appeler une des méthodes d’entrée
6
Moniteur: Vue schématique
7
Variables conditionnelles
sont accessibles seulement dans le moniteur
accessibles et modifiables seulement à l’aide de 2
fonctions:
x: wait bloque inconditionnellement la tâche appelante, lui
fait relâcher l'exclusion mutuelle sur le moniteur et la place
dans une file associée à condition
le processus pourra reprendre l’exécution seulement si
un autre processus exécute x: signal
x: signal reprend l’exécution d’un processus bloqué sur la
condition x
S’il en existe plusieurs: en choisir un (file?)
S’il n’en existe pas: ne rien faire
8
Moniteur avec variables conditionnelles
9
Premier exemple de synchronisation par moniteur
Soit à réaliser un point de synchronisation entre deux processus p et q, le
premier devant avoir terminé une séquence d'instructions (par exemple
avoir fini d'écrire) avant que le second ne soit autorisé à franchir ce point
(par exemple pour lire).
<processus p> <processus q>
Ecrire (); Synchro.Debut_Lire ();
[Link] (); Suite_q ();
Suite_p ();
moniteur Synchro ;
static boolean EcritureFaite = false;
static condition Fini; // la condition est supposée
initialisée à vide
void DebutLire ()
{ if (!EcritureFaite) [Link]; )
void FinEcrire ()
{ EcritureFaite = true ;
[Link];
} // FinEcrire()
Blocage dans les moniteurs
processus attendent dans la file d’entrée ou dans une file
de condition (ils n’exécutent pas)
sur [Link]: le processus est placé dans la file de la
condition (il n’exécute pas)
[Link] amène dans le moniteur 1 processus de la file x
(si x vide, aucun effet)
11
Un problème concernant le signal
Quand un processus P exécute [Link] et
libère un processus Q, il pourrait y avoir 2
processus qui peuvent exécuter, P et Q, ce
qui est défendu. Deux solutions possibles:
P pourrait attendre jusqu`à ce que Q sorte du
moniteur, [Link]. dans une file spéciale (dite urgente)
(v. Stallings)
Q pourrait attendre jusqu’à ce que P sorte du
moniteur
12
Monitor Producer_Consumer {
any_t buf[N];
int n = 0, tail = 0, head=0;
condition not_empty, not_full;
void put(char ch) {
if(n == N)
wait(not_full);
buf[head%N] = ch;
head++;
Moniteur
n++; Producteur -
signal(not_empty); Consommateur
}
char get() {
if(n == 0)
wait(not_empty);
ch = buf[tail%N];
tail++;
n--;
signal(not_full);
return ch;
}
}
Variables de condition et sémaphores
Variables de condition != sémaphores
● L'accès au moniteur est contrôlé par un verrou
● Wait : bloque le processus et abandonne le verrouillage du
moniteur
– Pour appeler wait, le processus doit être dans le moniteur,
d'où le verrou.
– Le sémaphore P() ne bloque le thread que si la valeur est
inférieure à 0
● Signal : provoque le réveil du thread en attente
– S'il n'y a pas de processus en attente, le signal est perdu
– V() incrémente la valeur, donc les futurs processus n'ont pas
besoin d'attendre P()
– Les variables de condition n'ont pas d'historique !
Cependant, ils peuvent être utilisés pour se mettre en œuvre l'un
l'autre