Explorer les Livres électroniques
Catégories
Explorer les Livres audio
Catégories
Explorer les Magazines
Catégories
Explorer les Documents
Catégories
La synchronisation de processus
1
Chapitre 3 : La synchronisation de processus
Introduction
Nous avons déjà dit que, si les processus étaient des entités autonomes et indépendantes, ils
pouvaient se trouver en conflit pour l'accès à certaines ressources communes. Ceci nécessite la
mise en œuvre de mécanismes dits de synchronisation pour gérer ces conflits. Par ailleurs, si
les processus sont en général indépendants, cela ne doit pas interdire la communication. La
conséquence de ces mécanismes est le blocage des processus en attente d'une ressource
momentanément indisponible. Deux problèmes en découlent : l'interblocage et la famine.
1. Mécanismes de synchronisation
Considérons un compte bancaire, dont le montant est mémorisé dans un emplacement donné A
sur disque. Le programme qui consiste à ajouter 100 à ce compte pourrait être le suivant, où N
est une variable locale du programme :
Lire (N, A);
N := N + 100;
Écrire (N, A);
N étant une variable locale du programme, implique qu'il en existe un exemplaire pour chacun
des deux processus.
Il s'ensuit que, si la valeur initiale du compte est 1000, on constate qu'après ces exécutions, il
est de 1100 au lieu de 1200. Les deux processus ne sont pas en fait totalement indépendants. Ils
partagent la ressource commune qu'est la valeur du compte bancaire à l'adresse A sur disque.
Cette ressource doit être à un seul point d'accès, c'est donc une ressource critique, et les
processus sont en exclusion mutuelle sur cette ressource critique.
2
Si la variable N est commune aux deux processus, le problème n'est pas résolu pour autant. En
effet l'instruction N := N + 100 n'est pas une instruction simple. En fait elle est décomposée
en trois instructions de la machine qui sont :
LOAD N
ADD 100
STORE N
L'allocateur du processeur prend en compte les instructions de la machine et non les instructions
du langage évolué pour déterminer les moments où il peut remplacer le processus actif par un
autre. En particulier, dans cet exemple, il est possible que le changement ait lieu juste après la
première instruction, donnant la séquence suivante :
Processus P1 Processus P2
LOAD N
LOAD N
ADD 100
STORE N
ADD 100
STORE N
Le problème provient du fait que le processus P2 a utilisé une variable partagée avant que P1
ait fini de s'en servir. Si l'on arrive à bien synchroniser les processus, le problème peut être
résolu.
Lorsqu'un processus accède à la variable IN, les autres processus ne doivent ni la lire, ni la
modifier jusqu'à ce que le processus ait terminé de la mettre à jour. D'une manière générale, il
faut empêcher les autres processus d'accéder à un objet partagé si cet objet est en train d'être
utilisé par un processus, ce qu'on appelle d'assurer l'exclusion mutuelle. Les situations de ce
type, où deux ou plusieurs processus lisent ou écrivent des données partagées et où le résultat
dépend de l'ordonnancement des processus, sont qualifiées d'accès concurrents.
2. Sections critiques
On appelle section critique la partie d'un programme où la ressource est seulement accessible
par le processus en cours. Il faut s'assurer que deux processus n'entrent jamais en même temps
en section critique sur une même ressource. A ce sujet, aucune hypothèse ne doit être faite sur
les vitesses relatives des processus.
3
Exemple : la mise à jour d'un fichier (deux mises à jour simultanées d'un même compte client).
La section critique comprend :
- modification du compte,
Le problème de conflit d'accès est résolût, si on peut assurer que deux processus ne soient jamais
en section critique en même temps au moyen de l'exclusion mutuelle. En général, les processus
qui exécutent des sections critiques sont structurés comme suit :
➢ Attente Passive : le processus passe dans l’état endormi et ne sera réveillé que lorsqu’il
sera autorisé à entrer en section critique.
- Section critique.
- Demande de sortie de la section critique.
- Section non critique.
Quatre conditions sont nécessaires pour réaliser correctement une exclusion mutuelle :
4
Il existe de nombreux mécanismes pour mette en œuvre l’exclusion mutuelle, dont chacun a ses
avantages et inconvénients :
Cette solution est dangereuse, car si le processus, pour une raison ou pour une autre, ne restaure
pas les interruptions à la sortie de la section critique, ce serait la fin du système. La solution
n'assure pas l'exclusion mutuelle si le système n'est pas monoprocesseur, car le masquage des
interruptions concernera uniquement le processeur qui a demandé l'interdiction. Les autres
processus exécutés par un autre processeur pourront donc accéder aux objets partagés.
Problèmes Cette méthode n'assure pas l'exclusion mutuelle : Supposons qu'un processus est
suspendu juste après avoir lu la valeur du verrou qui est égal à 0. Ensuite, un autre processus
est élu. Ce dernier teste le verrou qui est toujours égal à 0, met verrou à 1 et entre dans sa section
critique. Ce processus est suspendu avant de quitter la section critique. Le premier processus
est alors réactivé, il entre dans sa section critique et met le verrou à 1. Les deux processus sont
en même temps en section critique.
5
2.1.3. Utilisation de primitives (SLEEP et WAKEUP)
La primitive SLEEP() est un appel système qui suspend l'appelant en attendant qu'un autre le
réveille. WAKEUP(processus) est un appel système qui réveille un processus. Par exemple,
un processus H qui veut entrer dans sa section critique est suspendu si un autre processus B est
déjà dans sa section critique. Le processus H sera réveillé par le processus B, lorsqu'il quitte la
section critique.
Problème : Si les tests et les mises à jour des conditions d'entrée en section critique ne sont pas
exécutés en exclusion mutuelle, des problèmes peuvent survenir. Si le signal émis par
WAKEUP() arrive avant que le destinataire ne soit endormi, le processus peut dormir pour
toujours.
- une variable entière, ou valeur du sémaphore. Un sémaphore est dit binaire si sa valeur ne peut
être que 0 ou 1, général sinon.
Dans la plupart des cas, la valeur du sémaphore représente à un moment donné le nombre
d'accès possibles à une ressource (section critique).
6
L'opération UP(S) incrémente la valeur du sémaphore S, si aucun processus n'est bloqué par
l'opération DOWN(S). Sinon, l'un d'entre eux sera choisi et redeviendra prêt. UP(S) est aussi
une opération indivisible.
Algorithmes:
Semaphore mutex = 1;
Processus P1: Processus P2:
DOWN(mutex) DOWN(mutex)
UP(mutex); UP(mutex);
- Capteur de sortie = rôle de V (si S < = 0 feu vert pour une voiture)
Algorithmes:
Initialisation(sémaphore,n)
valeur[sémaphore] = n
- P(sémaphore)
valeur[sémaphore] = valeur[sémaphore] - 1
si (valeur[sémaphore] < 0) alors
étatProcessus = Bloqué
mettre processus en file d’attente
finSi
invoquer l’ordonnanceur
- V(sémaphore)
7
valeur[sémaphore] = valeur[sémaphore] + 1
si (valeur[sémaphore] == 0) alors
extraire processus de file d’attente
étatProcessus = Prêt
finSi
invoquer l’ordonnanceur
Les sémaphores permettent d’élaborer des mécanismes de plus haut niveau et de résoudre les
problèmes de synchronisation typiques :
2.2.2. Moniteurs
L’idée des moniteurs est d’offrir le support des exclusions mutuelles au niveau du langage. Un
moniteur est constitué d’un ensemble de données et de procédures regroupées dans un module
ayant comme propriété qu’un seul processus peut être actif dans le moniteur à un instant donné.
Moniteur file {
Int compteur = 0 ;
…
Procédure mettre (Objet o) {
}
…
Procédure retirer (Objet o) {
}
}
C’est le compilateur qui gère l’exclusion mutuelle au sein du moniteur et non plus le
programmeur, d’où le risque d’erreur est bien plus faible.
8
Une implémentation effective des moniteurs a été réalisée dans le langage Java au moyen de
qualificateur synchronized, et des méthodes wait et notify.
finsi finsi
Fait Fait
Règle 4 : Si le producteur est en attente parce que le tampon est plein, il doit être averti des que
cette condition cesse d'être vraie. De même, si le consommateur est en attente parce que le
tampon est vide, il doit être averti des que cette condition cesse d'être vraie.
Le tampon peut être représenté par une liste circulaire. On introduit donc deux variables
caractérisant l'état du tampon :
PRODUCTEUR : CONSOMMATEUR :
9
Faire toujours Faire toujours
Produire un objet si NPLEIN > 0
si NVIDE >0 alors NPLEIN <- NPLEIN - 1
alors NVIDE <- NVIDE - 1 sinon s'endormir
sinon s'endormir finsi
finsi prelever l'objet dans le
tampon
ranger l'objet dans le tampon
si producteur endormi
si consommateur endormi
alors reveiller le
alors reveiller le
producteur
consommateur
sinon NVIDE <- NVIDE + 1
sinon NPLEIN <- NPLEIN + 1
finsi
finsi
consommer l'objet
Fait
Fait
PRODUCTEUR CONSOMMATEUR
10
Fig. 2 : Problème des philosophes
- de privation : tous les philosophes prennent leur fourchette gauche, et, constatant
que la droite n'est pas libre, la reposent, puis prennent la droite en même temps, etc...
11
Fig. 3 : Problème du coiffeur endormi
4. Interblocage
Le modèle le plus commun d’opérations d’un système informatique est celui de processus qui doivent
partager l’accès à des ressources (UC, Mémoires, périphériques, …). Les problèmes d’accès à ces
ressources pouvaient être résolus par des stratégies de synchronisation faisant appel à des sémaphores
ou des moniteurs par exemple. Il est possible d’empêcher les processus d’accéder au même temps à une
ressource.
Même la meilleure technique de synchronisation ne peut toutefois garantir que chaque processus aura
accès aux ressources dont il a besoin et que d’autres processus ne restent pas éternellement bloqués en
attente. Ils sont dits dans un état d’interblocage.
12
D’une manière plus formelle, on peut identifier quatre conditions nécessaires pour qu’un
interblocage soit possible. Il faut que ces quatre conditions soient vérifiées simultanément pour
qu’un interblocage se produise.
1. Condition d’exclusion mutuelle : Il doit exister au moins deux ressources qui ne sont
pas partageables c.à.d. à un moment donné, chacune est soit attribuée à un processus,
soit disponible.
4. Condition d’attente circulaire : Il doit exister une chaine circulaire (cycle) d’au moins
deux processus dont chacun attend une ressource détenue par le membre suivant dans
la chaine.
Fig. 4 : Interblocage
- Une ressource est représentée par une boite rectangulaire. S’il existe plusieurs
instances indifférenciables de la ressource, on les représente dans la même boite. Par le
mot indifférenciable, on veut dire qu’un processus ne devait pas pouvoir choisir une
instance parmi d’autres, il prend la première disponible.
- Un arc qui part d’une instance d’une ressource R et pointe vers un processus P,
signifie que cette instance de R est détenue par P.
13
- Un arc qui part d’un processus P et pointe vers une instance d’une ressource R,
signifie que P est bloqué en attente d’une instance de R.
En fait, tout interblocage est signalé par la présence d'un tel cycle dans ce graphe, et
inversement, ce qui explique l'intérêt de cette représentation.
14
- Le nombre maximal d’instances de ces ressources dont il a besoin pour
déterminer son exécution et par différence le nombre d’instances des ressources qu’il
doit encore obtenir.
Exemple :
Pour avoir une image complète de l’état du système vis-à-vis de l’utilisation des ressources, il
nous faut encore préciser le nombre total d’instances de chaque ressource.
Ra Rb Rc Rd
10 11 9 11
Ra Rb Rc Rd
1 1 0 3
- État risqué : appelé aussi état incertain, à partir duquel l’interblocage est
inéluctable (inévitable).
Afin d’éviter qu’un interblocage se produise, il suffit, lorsqu’un processus présente au système
une demande d’allocation des ressources, de vérifier si le nouvel état obtenu serait un état
15
risqué, si c’est le cas, il faut refuser la ressource au processus ‘qui va rester donc bloqué en
attente de cette ressource). Sinon, le processus obtient la ressource demandée.
Par analogie a une banque, le nombre maximal est en quelque sorte le crédit total du processus
et le nombre alloué est l’encours (détenu). La somme totale des crédits peut être supérieure au
nombre des ressources réellement disponibles.
L’algorithme du banquier :
1. Construire la liste L
Répéter
2. Chercher parmi les processus de la liste L s’il y a un processus P dont les besoins
peuvent être satisfaits (nombre de ressources nécessaires<= nombre d’instances de
ressources disponibles)
3. S’il existe, on lui accorde les ressources dont il a besoin puis on le fait terminer. S’il
existe plusieurs choix pour P, on choisit le processus qui va libérer le maximum
d’instances de ressources.
4. Reconstruire le nouvel état du système : Mise à jour de L, des différentes matrices et les
ressources disponibles,
Jusqu’à ce qu’il n’y a plus de processus pouvant terminer.
S’il reste des processus dans L, alors l’état est risqué, sinon, l’état est sûr.
Les matrices d’allocation des ressources apportent donc des informations complémentaires à
celles offertes par les graphes d’allocation : Les graphes nous donnent une image instantanée
sur l’état du processus, mais ne nous permettent pas de prédire l’avenir, tandis que les matrices
d’allocation nous informent sur les futurs besoins de chaque processus et par conséquent les
risques d’interblocage.
Les graphes nous permettent de répondre à la question : l’état courant est-il un état
d’interblocage ?
16
Les matrices nous permettent de répondre aux questions :
17