Vous êtes sur la page 1sur 39

1

PROBLÈMES CLASSIQUES
DE SYNCHRONISATION
Anissa Omrane
Le dîner des philosophes
2

 Cinq philosophes chinois sont autour d’une table ronde,


chaque philosophe a sa propre assiette et une
baguette est disponible entre chaque pair d’assiettes.
Les philosophes réitèrent les phases de penser et de
manger.
 Pour manger un philosophe a besoin de deux
baguettes et il est autorisé à prendre une seule
baguette à la fois.
 Il est clair que c’est impossible que les philosophes
puissent manger en même temps.
Le dîner des philosophes
3

Le problème consiste à décrire


l’algorithme de chaque philosophe
pour qu’ils puissent alterner à l’infini
des phases de manger et de penser
sans qu’il y ait inter-blocages ou
famines.
Le dîner des philosophes
4

 Les philosophes mangent ou pensent


 Mangent avec 2 baguettes
 Prennent une seule baguette à la fois
 Comment prévenir les interbloquages ?
Algorithme trivial
5

Philosophe(i){
while (Vrai)
{ pense( );
prendre_ baguette(i);
prendre_ baguette((i+1)%5);
manger ( );
poser_ baguette( i );
poser_ baguette((i+1)%5);
}
}
Critiques de la solution triviale
6

 Un problème d'inter-blocage, si les N philosophes


décident de manger en même temps:
 En appliquant la procédure prendre_baguette(i).
 Tous les philosophes détiennent la baguette de droite et
attendent que celle de gauche se libère.
 Solution possible
 En introduisant une notion de délais aléatoires c’est-à-dire si
un philosophe obtient la première et n’obtient pas la seconde
baguette, il dépose sa baguette et recommence après un
délai aléatoire.
 Mais cette amélioration peut conduire à une situation de
famine.
Solution avec les sémaphores
7

 Un philosophe qui veut prendre les baguettes pour manger,


déclare qu'il a faim.
 Si l'un de ses deux voisins est en train de manger, il ne peut
donc pas prendre les deux baguettes et donc se met en
attente.
 Si les deux philosophes à côté ne mangent pas alors il peut
prendre les deux baguettes et déclarer qu'il mange.
 Quand le philosophe a fini de manger, il déclare qu'il
pense et regarde si ses deux voisins qui forcément ne
pouvaient pas manger, en ont dès lors l'opportunité.
 Si c'est le cas il les réveille.
Solution avec les sémaphores
8

 Un sémaphore est attribué à chaque philosophe.


 Etat = { PENSE , MANGE , A_FAIM}
sem Sem_prive [ N ] //initialisés à zéro
Etat Vect_etat[ N ] = { PENSE, …......., PENSE}
sem mutex = 1
Philosophe(i){
while (Vrai){
pense( );
prendre_baguettes(i);
manger ( );
poser_baguettes( i );
}
}
Solution avec les sémaphores
9

prendre_baguette (int i)
{
P(mutex);

Vect_etat [ i ] = A_FAIM;
test_mange( i );

V(mutex);
P(Sem_prive [ i ]);
}
Solution avec les sémaphores
10

poser_baguette (int i)
{
P(mutex);

Vect_etat [ i ] = PENSE;

test_mange((i+1)%N );
test_mange((i-1+N)%N );

V(mutex);
}
Solution avec les sémaphores
11

test_mange( int i )
{
if ( Vect_etat [ i ] == A_FAIM
&& Vect_etat [ (i+1)%N ] != MANGE
&& Vect_etat [ (i-1+N)%N ] != MANGE )
{
Vect_etat [ i ] = MANGE;
V(Sem_prive[ i ]);
}
}
Solution avec un moniteur
12

monitor dinerPhilosophe
{ // début moniteur

enum { PENSE; A_FAIM, MANGE) Etat [5] ;


condition File_privé[5];

initialization_code() {
for (int i = 0; i < 5; i++)
Etat[i] = PENSE;
}
Solution avec un moniteur
13

// suite moniteur
void prendre_baguettes (int i)
{
Etat[i] = A_FAIM;
test(i);
if (Etat[i] != MANGE)
File_privé [i].wait;
}
Solution avec un moniteur
14

// suite moniteur
void deposer_baguettes (int i)
{
Etat[i] = PENSE;
// test left and right neighbors
test((i + 4) % 5);
test((i + 1) % 5);
}
Solution avec un moniteur
15

// suite moniteur
void test (int i)
{
if ( (Etat[(i + 4) % 5] != MANGE)
&&(Etat[i] == A_FAIM)
&&(Etat[(i + 1) % 5] != MANGE) )
{
Etat[i] = MANGE ;

File_privé[i].signal () ;
}
}
}// fin Moniteur
Solution avec un moniteur
16

Philosophe(i)
{
while (Vrai)
{
pense( );

dinerPhilosophe.prendre_baguettes(i);
manger ( );
dinerPhilosophe.poser_baguettes(i);
}
}
Le problème des lecteurs/rédacteurs
17

 Problème classique qui permet de modéliser les accès à des


objets. Par exemple:
 Accès à un fichier

 Accès à un enregistrement dans un fichier ou une base de


données
 Dans une base de données, afin de conserver une cohérence, les
contraintes sont les suivantes :
 Plusieurs lecteurs doivent pouvoir lire la base de données en même
temps ;
 Si un rédacteur est en train de modifier la base de données, aucun
autre utilisateur (ni rédacteur, ni lecteur) ne doit pouvoir y accéder.
Le problème des lecteurs/rédacteurs
18

 Plusieurs lecteurs peuvent lire simultanément les données;


 Les rédacteurs s’excluent mutuellement;
 Les lecteurs et les rédacteurs s’excluent mutuellement.

 Il existe plusieurs variantes du problème : selon la priorité


accordée aux intervenants:
 Priorité aux lecteurs (famine possible des rédacteurs)
 Priorité aux rédacteurs (famine possible des lecteurs)
 Accès aux données selon les ordres des arrivées. Toutes les
demandes de lecteur qui se suivent sont satisfaites en même temps.
Le problème des lecteurs/rédacteurs
19

Variante n°1 : Priorité aux lecteurs.


Les règles sont les suivantes:
 Un lecteur peut accéder à la ressource si : Le
nombre de rédacteurs en cours d’écriture vaut 0
 Un rédacteur peut accéder à la ressource si:

 le nombre de lecteurs en attente de la ressource


vaut 0
 le nombre de lecteurs en cours de lecture vaut 0

 Le nombre de rédacteurs en cours d’écriture vaut 0


Le problème des lecteurs/rédacteurs
20

Variante n°1 : Priorité aux lecteurs


 Une variable nbLecteurs

 mutexLecteurs, qui est en charge de protéger l’accès à la

variable nbLecteurs.
 redacteur, qui permet au premier lecteur qui accède la

ressource de bloquer les futurs rédacteurs. Il permet également


au rédacteur accédant la ressource de bloquer les lecteurs
pendant l’écriture.
 mutexRedacteurs, qui permet au rédacteur accédant la
ressource de bloquer les autres rédacteurs. De ce fait, un seul
rédacteur ne peut être en attente du sémaphore redacteur,
empêchant ainsi un rédacteur de brûler la priorité à un lecteur.
Le problème des lecteurs/rédacteurs
21

Variante n°1 : Priorité aux lecteurs

Sémaphore mutexLecteurs initialisé à 1 ;


Sémaphore mutexRedacteurs initialisé à 1 ;
Sémaphore redacteur initialisé à 1 ;
int nbLecteurs=0;
Le problème des lecteurs/rédacteurs
22

Lecteur Rédacteur
void debutLecture() { Void debutEcriture() {
P(mutexLecteurs);
nbLecteurs++;
if (nbLecteurs==1)
P(mutexRedacteurs);
P(redacteur);
P(redacteur); }
V(mutexLecteurs);
} void finEcriture() {
V(redacteur);
void finLecture() { V(mutexRedacteurs);
P(mutexLecteurs); }
nbLecteurs--;
if (nbLecteurs==0)

V(redacteur);
V(mutexLecteurs);
}
Le problème des lecteurs/rédacteurs
23

Lecteur () Rédacteur()

debutLecture() debutEcriture()

Lectures(); Rédaction ()

finLectures() finEcriture()
Le problème des lecteurs/rédacteurs
24

Variante n°2 : Priorité aux rédacteurs.


 Un lecteur ne peut lire que si aucun rédacteur n’est présent ou
en attente. Les règles sont les suivantes :

 Un lecteur peut accéder à la ressource si:


 Le nombre de rédacteurs en cours d’écriture vaut 0
 Le nombre de rédacteurs en attente d’écriture vaut 0

 Un rédacteur peut accéder à la ressource si:


 Le nombre de lecteurs en cours de lecture vaut 0
 Le nombre de rédacteurs en cours d’écriture vaut 0
Le problème des lecteurs/rédacteurs
25

 Une variable nbLecteurs


 mutexLecteurs, qui permet de bloquer les lecteurs pendant que
des écritures sont en cours.
 mutexRedacteurs, qui permet de bloquer les rédacteurs
pendant que des écritures ou des lectures sont en cours.
 mutex, qui est en charge de protéger l’accès à la variable
nbLecteurs.
 redacteur, qui permet au premier lecteur qui accède la
ressource de bloquer les potentiels rédacteurs.
 lecteur, qui permet au premier rédacteur arrivé de bloquer
les potentiels futurs lecteurs.
Le problème des lecteurs/rédacteurs
26

Variante n°2 : Priorité aux rédacteurs.


semaphore mutexLecteurs initialisé à 1;
semaphore mutexRedacteurs initialisé à 1;
semaphore lecteur initialisé à 1;
semaphore redacteur initialisé à 1;
semaphore mutex initialisé à 1;
int nbLecteurs, nbRedacteurs;
Priorité aux rédacteurs
nbLecteurs=0;
nbRedacteurs=0;
Le problème des lecteurs/rédacteurs
27

Lecteur Rédacteur
void debutLecture() { void debutEcriture() {
P(mutexLecteurs); P(mutexRedacteurs);
P(lecteur); nbRedacteurs++;

P(mutex); if (nbRedacteurs==1)
nbLecteurs++; P(lecteur);
if (nbLecteurs==1)
P(redacteur); V(mutexRedacteurs);
V(mutex); P(redacteur);
}
V(lecteur);
V(mutexLecteurs);
} void finEcriture() {
V(redacteur);
void finLecture() { P(mutexRedacteurs);
P(mutex);
nbLecteurs--; nbRedacteurs--;

if (nbLecteurs==0) if (nbRedacteurs==0)
V(redacteur); V(lecteur);
V(mutex); V(mutexRedacteurs);
}
}
Le problème des lecteurs/rédacteurs
28

Variante n°3 : FIFO.


 Les demandes d’accès à l’objet sont servies dans l’ordre
d’arrivée.
 S’il y a plusieurs lecteurs consécutifs, ils sont servis ensemble.
Les règles sont les suivantes :
 Un lecteur peut accéder à la ressource si:
 Le nombre de rédacteurs en cours d’écriture vaut 0
 Un rédacteur peut accéder à la ressource si:
 Le nombre de lecteurs en cours de lecture vaut 0
 Le nombre de rédacteurs en cours d’écriture vaut 0
Le problème des lecteurs/rédacteurs
29

Variante n°3 : FIFO.


 Une variable nbLecteurs.

 mutex, qui est en charge de protéger l’accès à la

variable nbLecteurs.
 redacteur, qui permet au premier lecteur qui
accède la ressource de bloquer les futurs rédacteurs.
Il permet également au rédacteur accédant à la
ressource de bloquer les lecteurs pendant l’écriture.
 fifo, une file d’attente dans laquelle passent tous

les lecteurs et les rédacteurs.


Le problème des lecteurs/rédacteurs
30

semaphore mutex initialisé à 1;


semaphore fifo initialisé à 1;
semaphore redacteur initialisé à 1;

int nbLecteurs;

nbLecteurs=0;
Le problème des lecteurs/rédacteurs
31

Lecteur Rédacteur

void debutLecture() { void debutEcriture() {


P(fifo); P(fifo);
P(mutex); P(redacteur);
nbLecteurs++;
}
if ( nbLecteurs==1)
P(redacteur);

V(mutex);
V(fifo);
}

void finLecture() { void finEcriture() {


P(mutex);
V(redacteur);
nbLecteurs--;
if ( nbLecteurs==0) V(fifo);
V(redacteur); }

V(mutex);
}
Le problème des lecteurs/rédacteurs
32
Solution avec les moniteurs
33

La solution présentée est conforme aux règles suivantes


(Priorité au lecteurs)

 Lorsque des lectures sont en attente de la terminaison d'une


écriture, elles sont prioritaires sur la prochaine écriture.

 Lorsque des écritures sont en attente, une nouvelle lecture


est placée en attente.
Solution avec les moniteurs
34 34

type Lecteurs_Rédacteurs = Moniteur // début moniteur


{ Booléen Ecriture ;
int nbLecteurs;
Condition Lecteur, Ecrivain ;

void Debut_Lecture() {
If (Ecriture) || ! (Ecrivain.Vide())
Lecteur.Wait();
nbLecteurs= nbLecteurs+ 1 ;
Lecteur.Signal() ;
}
void Fin_Lecture() {
nbLecteurs= nbLecteurs- 1 ;
If ( nbLecteurs== 0) (Ecrivain.Signal()) ;
}
Solution avec les moniteurs
35

void Debut_Ecriture() {
If (nbLecteurs> 0) || (Ecriture) )
Ecrivain.Wait() ;
Ecriture = Vrai ;
}

void Fin_Ecriture(){
Ecriture = Faux ;
If ! (Lecteur.Vide()) Lecteur.Signal();
Else
Ecrivain.Signal() ;
}
Constructeur(){
Ecriture = Faux ;
nbLecteurs = 0 ;
}
Solution avec les moniteurs
31

Lecteur () Rédacteur
{ {
..... .....
..... .....
While(1) While(1)
{ {
Debut_Ecriture() ;
Debut_Lecture() ; Fich.Ecrire(...) ;
Fin_Ecriture() ;
Fich.Lire(...) ;
}
Fin_Lecture()
; }

}
}
Le problème du barbier endormi (1)
37
Le problème du barbier endormi (2)
38
Le problème du barbier endormi (3)
31

Vous aimerez peut-être aussi