Cours ExcMut
Cours ExcMut
1
1 Introduction
Exposé du problème
1 Introduction
La notion de « Concurrence »
Définition :
« Rivalité d’intérêt entre entités provoquant une compétition »
Ressources physiques [à partager car en nombre insuffisant]
Processeur, disque, imprimante, …
Ressources logiques [leur rôle est de conserver ou mémoriser
des données, un état commun]
Données globales du Système d’Exploitation
Zones de mémoire partagée
Fichiers d’une base de données
2
1 Introduction
Rôle des solutions proposées
But: Contrôler la concurrence
Organiser la compétition:
Fournir des services de synchronisation indirecte par
exclusion mutuelle : « Arbitrage », rôle du système
Ou au contraire, inclure la partie contrôle de concurrence
au sein des programmes : « sans arbitrage » par le système
Coordonner l’utilisation des ressources:
Empêcher ou réparer des blocages, garantir l’équité ou
absence de famine
1 Introduction
Illustrations (1/3)
Exemple 1 :
Pour tout i, Pi ne doit pas imprimer tant que une
autre impression est en cours !
Processus P Processus Q
… …
imprimer(ligne l1) imprimer(ligne k1)
imprimer(ligne l2) imprimer(ligne k2)
… …
3
1 Introduction
Illustrations (2/3)
Exemple 2 :
Une instruction assembleur est indivisible, mais
pas une suite d’instructions
P(Virement nP)
nP) Q(Virement nQ)
nQ)
… …
n:=n+nP
n:=n+nP n:=n+nQ
n:=n+nQ
Actions_P : Actions_Q :
1. load Reg_P, n 1’. load Reg_Q, n
2. add Reg_P, nP 2’. add Reg_Q, nQ
3. store Reg_P, n 3’. store Reg_Q, n
… …
1 Introduction
Illustrations (3/3)
Exemple 2 (suite)
Entrelacements possibles lors de l’exécution des actions Action_P et
Action_Q
Actions_P : Actions_Q :
1. load Reg_P, n 1’. load Reg_Q, n
2. add Reg_P, nP 2’. add Reg_Q, nQ
3. store Reg_P, n 3’. store Reg_Q, n
1, 2, 3, 1’, 2’
2’, 3’
3’ n=n+nP
n=n+nP++nQ
1’, 2’
2’, 3’
3’, 1, 2, 3
OK !
1, 1’, 2, 2’, 3, 3’
1, 2, 1’, 2’
2’, 3, 3’
1, 1’, 2’
2’, 2, 3, 3’ n=n+nQ
n=n+nQ
1, 2, 1’, 3, 2’, 3’
3’ PBM : nP perdu !
1, 1’, 2, 3, 2’, 3’
3’
1’, 1, 2’, 2, 3’, 3
1’, 2’
2’, 1, 2, 3’, 3 n=n+nP
n=n+nP
1’, 1, 2, 2’, 3’
3’, 3 PBM : nQ perdu !
1’, 2’
2’, 1, 3’, 2, 3
1’, 1, 2’, 3’
3’, 2, 3 Il faut que : 3 pré
précède (<) 1’
1’ ou 3’
3’ < 1
Donc, que Actions_P < Actions_Q ou Actions_Q < Actions_P
4
1 Introduction
Solution au Problème
Imposer que les sections critiques soient exécutées
de manière non entrelacée
pour garantir une utilisation correcte des ressources
L’imprimante dans l’exemple 1
La variable n dans l’exemple 2
1 Introduction
« Section Critique » et « Exclusion Mutuelle »
5
1 Introduction
Protocole d’
d’entré
entrée en Demande de la ressource
section critique
<section de code critique> <section de code critique>
Protocole de sortie de
section critique Libé
Libération de la ressource
1 Introduction
Propriétés attendues d’une solution (1/2)
1. Exclusion mutuelle
A tout instant, un processus au plus exécute des instructions de sa
section critique
2. Absence de blocage (permanent)
Si plusieurs processus attendent pour entrer en SC, et si aucun
processus n’est déjà en SC, alors un des processus qui attend doit
pouvoir entrer en SC au bout d’un temps fini
3. Condition de progression (cad. blocage que temporaire)
Un processus qui se trouve hors de sa SC et hors du protocole
contrôlant l’accès à la SC ne doit pas empêcher un autre processus
d’entrer dans sa SC : un processus ne doit pas ralentir un autre
6
1. Introduction
Propriétés attendues d’une solution (2/2)
7
2 Solutions avec attente active
Protocoles de gestion de Section Critique
Principe :
Une entité désirant entrer en SC attend de façon active qu’une
condition soit vérifiée (ici, aucune autre entité en SC)
8
2 Solutions avec attente active
Solutions dites « logicielles » (1)
Algorithme 1 : une solution « naïve »
P1 P2
Répéter Répéter
Tant que (Tour = 2) Faire Tant que (Tour = 1) Faire
sleep(d
sleep(dé
élai); sleep(d
sleep(dé
élai);
Fintantque Fintantque
<section critique> <section critique>
Tour :=2 Tour :=1
Jusqu’à
Jusqu’à faux Jusqu’à
Jusqu’à faux
9
Solutions dites « logicielles » (3)
[Peterson 1981]
Correct, généralisable à N processus (mais N
fixé à l’avance…)
Tour : variable commune, initialement =1 (par ex)
Drapeau1, Drapeau2, initialement = faux
(quand tour =i, Pi peut entrer en SC)
P1 P2
… …
Drapeau1 = vrai ; Tour:=2
Tour:=2 Drapeau2 = vrai ; Tour:=1
Tour:=1
Tant que (Drapeau2 ET Tour=2
Tour=2) Tant que (Drapeau1 ET Tour=1
Tour=1)
Faire sleep(d
sleep(déélai); Faire sleep(d
sleep(déélai);
Fintantque Fintantque
<section critique> <section critique>
Drapeau1 := faux Drapeau2 := faux
… …
P1 en SC => P2 en SC =>
ET
Drapeau2=faux OU Tour =1 Drapeau1=faux OU Tour =2
P1 en SC => P2 en SC =>
ET
Drapeau1 = vrai Drapeau2 = vrai
10
2 Solutions avec attente active
Solutions dites « logicielles »(5)
Analyse algorithme Peterson (suite)
Absence de blocage
Preuve par l’absurde : supposons P1 et P2 sont incapables de
terminer leur protocole d’entrée en SC (cad bloqués
simultanément) dans Tant que
Drapeau2=vrai
ET
Drapeau1= vrai
ET Tour = 2 ET Tour = 1
Drapeau2 = faux
Drapeau2=vrai ET Tour = 2
Drapeau2 = faux ET
Donc Drapeau2 = vrai => Impossible !
11
2 Solutions avec attente active
Solutions dites « logicielles » (7)
12
2 Solutions avec attente active
Solutions de niveau Matériel (2)
Utilisation d’une instruction CPU : Test-And-Set (TAS)
prev = TAS(var) exécute de façon réellement indivisible :
1. prev = var
2. var = 1
Intérêt : deux (plusieurs) entités ne peuvent pas (avoir
l’impression de) faire passer la variable de la valeur 0 à la valeur
1 en même temps :
1. Celui qui fait passer la variable de la valeur 0 à la valeur 1 le sait (en
sortie, prev = 0)
2. Celui qui NE peut PAS faire passer la variable de la valeur 0 à la
valeur 1 le sait aussi (en sortie, prev = 1)
⇒ Celui qui gagne est celui parvient à faire passer la valeur de la
variable de 0 a 1 (celui qui récupère prev = 0).
13
2 Solutions avec attente active
Solutions de niveau Matériel (4)
Analyse de la solution basée sur TAS :
Exclusion mutuelle : Ok
Absence de blocage : Ok
Condition de progression : Ok
Absence de famine :
Ok si l’ordonnanceur l’assure (cad si n’active pas Pi
éternellement),
sinon, c’est NON
si Pi quitte sa SC, garde le CPU et se présente à nouveau à
l’entrée de la SC : verrou toujours à 0, donc Pi entre à
nouveau… (remarque applicable aussi pour sol.
« Masquage »)
Code identique : Ok
14
2 Solutions avec attente active
Bilan
Solutions avec attente active gourmandes en
temps CPU
Solutions ad-hoc:
programmation plus technique, source d’erreurs si
on oublie de libérer la SC
L’équité dépend souvent entièrement de
l’ordonnanceur, or il n’est pas explicitement
sollicité
Un processus peut garder le CPU suffisamment
longtemps et faire ainsi plusieurs entrées en SC
sans que ceux qui attendent puissent avoir leur
tour
15
Concurrence entre processus &
Exclusion Mutuelle
1. Introduction
2. Solutions avec attente active, dites Sans Arbitrage
3. Solutions avec blocage (attente passive), dites
Avec Arbitrage
16
3 Solutions avec blocage
Principe de fonctionnement
Répéter
…
1 Est-
Est-ce que je peux entrer en SC (je demande ceci à l’arbitre) ?
2 Si NON alors je me bloque …
<section critique>
Je relâche la SC (en le disant à l’arbitre), et la question se pose :
Est-
Est-ce qu’
qu’un processus est bloqué
bloqué ?
Si OUI alors le ré
réveiller (ou Ordonner un ré réveil)
Jusqu’à
Jusqu’à faux
17
3 Solutions avec blocage
Sémaphores [Dijkstra, 1965]
Outil général, pouvant servir à réguler d’autres interactions de
nature « Synchronisation » entre entités :
permettre à un nombre borné (éventuellement plus grand que 1)
d’entités d’entrer en section critique
Attendre qu’un nombre minimal d’entités soient bloquées avant que
l’une d’elles puisse continuer (rendez-vous)
…
Description
Sémaphore = type abstrait
structure de données (compteur + file d’attente d’entités)
interface (opérations, dont initialisation, sur la structure de données)
18
3 Solutions avec blocage
Sémaphores: opération P
Opé
Opération P(s:semaphore
P(s:semaphore))
Si (s.Val
(s.Val <=0)
Alors //ranger le descripteur du processus dans s.File
ajouter (s.File
(s.File,, descripteur processus courant);
//mettre le processus dans l’é l’état
tat bloqué
bloqué
descripteur courant . Etat = BLOQUÉ
BLOQUÉ
//choisir un nouveau processus à rendre actif
faire appel à l’ordonnanceur pour qu’ qu’il choisisse
Sinon s.Val := s.Val – 1;
FinSi
Opé
Opération V(s:semaphore
V(s:semaphore))
Si (s.File
(s.File non vide)
Alors //retirer
//retirer de s.File le descripteur d’
d’un processus
P= retirer (s.File
(s.File))
// mettre ce processus dans l’é l’état
tat prêt
P. etat = PRÊ
PRÊT
Sinon s.Val := s.Val + 1;
FinSi
19
3 Solutions avec blocage
Sémaphores : utilisation pour résoudre EM
Pi pour tout i :
Répéter
<hors section critique…
critique…>
P(Mutex
P(Mutex))
<section critique>
V(Mutex
V(Mutex))
<hors section critique…
critique…>
Jusqu’à
Jusqu’à …
20
3 Solutions avec blocage
Moniteurs
[Hoare, 1974 – Brinch Hansen, 1975]
Motivation : à cette époque, émergence du concept de type
abstrait: structure de donnée cachée manipulée par des
opérations de spécification connue (précurseur d’objet!)
D’où l’idée évidente : intégrer les protocoles d’entrée et de
sortie de SC au début et à la fin des opérations spécifiées comme
devant s’exécuter en exclusion mutuelle
C’est le compilateur qui rajoute les instructions du protocole
d’entrée et de sortie, souvent à base de sémaphores.
21
3 Solutions avec blocage
Moniteurs (2)
Exemple de moniteur : gestion de compte bancaire
procé
procédure Etat /* en exclusion mutuelle avec Virement */
début
imprimer solde;
solde;
fin
procé
procédure Virement(montant
Virement(montant : entier) /* en exc. mut. avec Etat & Virement */
début
solde := solde + montant;
montant;
fin
Activité
Activité P :
…
Un_compte.Virement(
Un_compte.Virement(nP);
nP); Activité
Activité R :
… …
Un_compte.Virement(
Un_compte.Virement(nR);
nR);
…
Activité
Activité Q : Un_compte.
Un_compte. Etat();
… …
Un_compte.Virement(
Un_compte.Virement(nQ);
nQ);
Un_compte.
Un_compte. Etat();
…
22
3 Solutions avec blocage
Synchronisation en Java : moniteur
class ExMut {
int cpt; // shared data of the instance
Eléments synchronisés : public synchronized void dec() {
Objets cpt--; // c’est une section critique
}
Classes public synchronized void inc() {
Principes d’un moniteur cpt++; // c’est une autre SC
}
Méthodes synchronisées = }
exécutées en exclusion
class SynchroCond {
mutuelle int cpt; // shared data
Opérations wait et public synchronized void get() {
if (cpt <= 0) wait();
notify/notifyAll cpt--; // c’est bien sûr une SC !
pour gérer une }
public synchronized void put() {
unique variable de condition
cpt++;
associée au moniteur notify();
}
}
23
3 Solutions avec blocage
Principe mise en oeuvre moniteur en
Java (2/2)
Tout objet et toute classe possèdent en plus
une file de processus bloqués
Parce qu’un moniteur Java fournit une (seule) var.
de condition (anonyme)
wait() :
put(current_thread, blocked) notify() :
current.unlock() // le moniteur devient libre if !empty(blocked) {
<stop the current thread> thread = get(blocked)
current.lock() // la thread doit acquérir de wakeup(thread)
// nouveau le verrou en se réveillant, }
//car, l’exécution se poursuivra DANS le
// moniteur
}
24
3 Solutions avec blocage
Classe Sémaphore de Java 1.5+
class Semaphore { // import java.util.concurrent.Semaphore
4 Conclusions
Bilan des mises en oeuvre d’outils
de synchronisation
Pour implanter les outils de synchronisation avec
attente (forcément!), on a besoin d’autres outils pour
gérer de l’exclusion mutuelle
atomicité d’une séquence d’instructions, aussi (de)bloquer un
processus
en pratique, ce sont des solutions de plus bas niveau
d’abstraction. Exemples :
Masquer les interruptions durant l’exécution de P
ou utiliser l’algo avec TAS, basé sur attente active pour
implanter la primitive P
Bloquer un processus, ranger son contexte, le rendre éligible à
partir de son contexte, dans l’implantation d’un P ou V
Ou utiliser des sémaphores ou des verrous (sémaphore ultra
simplifié) pour implanter un moniteur
25
4 Conclusions
Ne pas systématiquement bloquer ! (1/2)
With locking, if one thread attempts to acquire a lock that is
already held by another thread, the thread will block until the
lock becomes available. This approach has some obvious
drawbacks, including the fact that while a thread is blocked
waiting for a lock, it cannot do anything else. This scenario could
be a disaster if the blocked thread is a high-priority task (a
hazard known as priority inversion).
Concurrent algorithms based on TAS (+/- CAS) are called lock-
free (also non-blocking), because threads do not ever have to
wait for a lock (sometimes called a mutex – mutual exclusion
lock). Either the TAS operation succeeds or it doesn't, but in
either case, it completes in a predictable amount of time. If the
TAS fails, the caller can retry the TAS operation or take other
action as it sees fit.
Atomic variable de JDK 5+ : variable volatile, permet d’être accédée
(consultation ou modification) en exclusion mutuelle, d’une manière
efficace grâce à l’utilisation d’un TAS (la SC est très courte)
Voir package java.util.concurrent.atomic
4 Conclusions
Ne pas systématiquement bloquer ! (2/2)
26