Vous êtes sur la page 1sur 92

Dr.A.

Adouane 1
La synchronisation des processus permet de définir et de
réaliser :

Les règles d’accès simultanés aux ressources partagées

Des mécanismes de contrôle permettant d’imposer ces règles


aux processus

La possibilité de faire attendre un processus qui tenterait des


actions ne respectant pas ces contraintes
Types de parallélisme :

Processus disjoints (Indépendants) qui n’ont aucune relation


commune. Leurs exécutions respectives sont indépendantes
et leurs contextes respectifs sont disjoints

Processus concurrents qui interagissent les uns avec les


autres durant leur évolution, cela implique des processus qui
fonctionne en parallèles et d’autre séquentiellement
Types d’interactions

Compétition. Les processus ne se connaissent pas mais ils


rentrent en conflits pour l’utilisation des ressources
communes/partagées

Coopération. Les processus se connaissent mutuellement et


échangent des informations (communiquent) pour traiter un
même problème. Ils peuvent aussi rentrer en compétition
pour des ressources partagées.
La synchronisation se fait par les mécanismes suivants :

Exclusion Mutuelle

Régions Critiques

Sémaphores

Moniteurs
Dans le système d’exploitation, les processus (thread) peuvent
partager des ressources communes, plusieurs problèmes peuvent
survenir.

Exemple 1: spouleur d’impression


2 processus entre en jeux:
◦ Un processus qui écrit le nom de qui veut imprimer dans un répertoire de
spoule
◦ Un démon d’impression qui périodiquement vérifie et imprime le fichier dans
le répertoire, et supprime le nom du répertoire après impression

Le répertoire contiens beaucoup d’entrées de 0 à N, chaque une


prend un nom de fichier
Deux variables disponible pour tous les processus sont
utiliser :
◦ Out qui pointe le prochain fichier à imprimer
◦ in qui pointe la prochaine entrée libre du répertoire

À un moment on a les entrées de 0 à 3 libres, et de 4 à 6


pleines

Pratiquement au même moment 2 processus A et B veulent


rajouter leur fichier dans le répertoire d’impression
On suppose que A arrive légèrement avant B, il lit le in est trouve 7
qu’il sauvegarde dans une variable locale next_free_slot, à ce
moment la son temps CPU est écouler, le processus décide de
l’arrêté et d’exécuter B

B va à son tour lire le in et sauvegarde la valeur 7 trouvé dans sa


propre variable next_free_slot

Les 2 processus voient donc que in contient la valeur 7

B ayant encore du temps CPU va écrire le nom de fichier dans le


répertoire et incrémenter le in à 8
Quand A reprend l’exécution, il va écrire son nom de fichier sur
l’entrée 7 en écrasant le fichier de B, et incrémente ensuite in à 8

Du point de vu du spouler, il n y a aucune erreur dans le répertoire,


il imprime donc le fichier de A sans erreur, le processus B quant à
lui va attendre indéfiniment sont fichier qui ne s'imprimera jamais !

Les situations comme celle-ci où plusieurs processus lisent et


écrivent sur les même fichiers avec le résultat qui dépend de
l’ordre de passage sont nommées Condition de concurrence
Les conditions de concurrence doivent à tout prix être éviter
dans les programmes, pour cela il faut interdire la lecture et
écriture simultané sur les mêmes ressources partagées (
fichiers, mémoire…)

Le but est donc de s’assurer que si un processus utilise une


ressource partagé, aucun autre processus ne pourra intervenir
sur cette ressource tant qu’il n’aura pas fini

Ce mécanisme est appelé Exclusion Mutuelle


Exclusion Mutuelle :
Problème d’accès simultané à une ressource en écriture !

Exemple 2, algorithme de réservation


Deux clients dans deux agences différentes veulent réserver le même
billet, l’algorithme de réservation est le même, il fonctionne comme suit
:

si nbplace > 0
alors
réserver une place;
nbplace = nbplace – 1;
Save
La variable nbplace, qui représente le nombre de places
restantes dans l’avion par exemple, est ici une variable d’état
du système (de réservation).

On considère l’exécution de deux processus Client_1 et


Client_2

Les 2 processus sont exécuté pour réservé les places des


clients
Client_1 s’exécute en premier, et entame une réservation et
test la valeur de la variable nbplace (nbplace = 1)

Client_1 est commutée par l’ordonnanceur juste après le test


du nombre de places,

Client_2 s’exécute à son tour, teste nbplace qu’il trouve


également égale à 1

Client_2 fait une réservation et nbplace devient égale à 0


Client_1 reprend la main avec son test nbplace = 1, il peut
donc réserver une place

Il continue son exécution en décrémentant à son tour nbplace


> nbplace = -1 !!

nbplace devient égale à – 1 ce qui est incohérent ! Une même


place a été allouée à deux clients différents !
Les processus Client_1 et Client_2 doivent être exécutées en
Exclusion Mutuelle.

Nbplace représente la ressource critique

les séquences de lecture, modification et d’écriture


s’appellent sections critiques
La section critique doit garantir que la ressource critique
manipulée durant la section critique ne peut effectivement
être utilisée que par un seul processus à la fois.

Pour garantir l’exclusion mutuelle, il faut entourer l’utilisation


de la variable nbplace d’un prélude et d’un postlude
Le prélude prend la forme d’une protection qui empêche un
processus de manipuler la variable nbplace si un autre
processus le fait déjà.

Le postlude prend la forme d’une fin de protection qui libère


la ressource nbplace et la rend accessible au processus
Client_2.
Dans le cas où le prélude et le postlude sont mal construit, on se
retrouve dans l’un des cas :

L’interblocage qui caractérise une situation ou les processus ne


peuvent plus progresser par manque de ressources. Chaque
processus détient des ressources dont l’autre a besoin.

La famine qui est une situation où certains processus n’accèdent


jamais à leurs sections critiques et sont ainsi mis en attente
indéfiniment alors que d’autre accèdent à leurs section critiques
selon leurs besoins.
Pour étudier et comparer les solutions au problème de l’EM, on se
donne un ensemble d’hypothèses de travail (énoncées par
DIJKSTRA) :

Les vitesses relatives des processus en compétition sont


quelconques et inconnues .

La solution doit éviter qu’un blocage mutuel des processus en


attente de la ressource critique dure indéfiniment alors que celle-ci
est libre

Si un processus est bloqué hors de sa SC, ce blocage ne doit pas


empêcher l’entrée d’un autre processus en SC.
A tout instant , un processus au plus peut se trouver en section
critique

Si aucun processus n’est en SC et que plusieurs processus sont en


attente de la ressource critique, alors l’un d’eux doit pouvoir y
entrer au bout d’un temps fini.

L’ordre d’accès à la ressource critique est quelconque

La solution doit être la même pour tous les processus ; aucun


processus ne doit jouer un rôle privilégié
Le fonctionnement souhaité entre deux processus est comme
suit :

Le processus A rentre en section critique à l'instant T1

Le processus B arrive plus tard à T2 est tente de rentrer lui


aussi, B ne peut pas rentrer car A est déjà dans la section
critique

Le processus B est suspendu jusqu’à ce que A finisse et sort


de la section critique à l’instant T3
Masquage des
Interruptions

Solutions
Instructions Spéciales
Matérielles

Réalisation
de l’EM Attente Active

Solutions Verrous
Logicielles
Sémaphores
Attente Passive
Moniteurs
L’attente active : un processus boucle sur une condition et l’évaluer
de manière répétitive jusqu’à ce qu’elle change d’état.

la demande d’entrée aura la forme d’une boucle d’attente active :


Répéter
// rien
Jusqu'à (Condition d’entrée en SC vraie) ;
Tant que(Condition d’entrée en SC fausse)
Faire DTQ
// rien
FTQ ;
Inconvénients:
En considérant l’attente active, tout processus désirant entrer en
SC est susceptible de consommer du temps (éventuellement tout
son quantum de temps, voire même plusieurs) en bouclant
inutilement.

Cette attente équivaut à une forme d’autoconsommation du


système. Le temps d’allocation de la ressource principale, c.à.d.,
du processeur est fâcheusement gaspillé.

Une solution à ce problème consiste à mettre provisoirement le


processus ne pouvant entrer en SC dans état d’attente passive.
Si un processus veut accéder à une ressource, et que celle-ci
est déjà utilisé le processus devra attendre

L’attente passive consiste à bloquer le processus sans qu’il ne


consomme du temps CPU

L'utilisation de l'attente passive permet de laisser la ressource


processeur disponible à un autre thread

L'attente passive doit être évitée si le temps d'attente prévu


est inférieur à la durée de la commutation de contexte
Matériellement :

Interdisant (masquant) les interruptions durant la modification


d’une variable pour être sur que la séquence courante
d’instructions s’exécute en ordre sans aucune réquisition

Utilisant des instructions matérielles spéciales qui permettent


soit de tester et modifier le contenu d’un mot-mémoire (Ex:
instruction TAS), soit d’échanger le contenu de deux mots (Ex:
instruction SWAP) d’une manière atomique (indivisible).
Dans un ordinateur monoprocesseur, si on désactive les interruptions, le
processus en cours ne sera pas arrêté car il n’y a pas de signal d’horloge
pour basculer entre les processus.

Une fois qu’un processus à désactiver les interruptions, il peut utiliser la


ressource partager sans risque d’intervention d’un autre processus

Si le système est multiprocesseur, bloquer l’interruption d’un CPU ne


garantie pas qu’un autre CPU ne produise pas une interruption sur cette
ressource.

Cette solution n’ai pas très viable, car si le processus ne réactive pas les
interruptions tout le système sera en panne !
Masquage des Interruptions: Il faut rendre les SC indivisibles en
inhibant, durant leur exécution, les interruptions par masquage.

N’est accessible qu’aux programmeurs privilégies (super utilisateurs) pour


des raisons de fiabilité.
Fonctionnel que sur des machines monoprocesseurs
Instructions Spéciales: permettent de lire et de modifier une
ou plusieurs variables communes d’une manière indivisible en
une seule instruction (instructions atomiques).

Par conséquent, si deux processus exécutent simultanément


ces instructions, l’un d’eux sera mis en attente

Fonctionnelle sur des machines multiprocesseurs


La désactivation des interruptions sur un CPU pour faire une
lecture écriture sur la mémoire, ne garantie pas qu’après
lecture de la donnée un autre CPU ne fasse pas une
interruption avant l’écriture

Si on veut empêcher l’accès à la mémoire tout au long des


instructions de lecture écriture, il est nécessaire de bloquer le
bus mémoire

Il est donc nécessaire de rajouter un composant matériel pour


permettre le verrouillage du bus mémoire
Cette solution matérielle vient d’une instruction utilisé dans les
ordinateurs multicœur : TSL RX, Lock : test and set lock

Le processus qui veut accéder à la ressource lit le mot lock dans le


registre RX

Lorsque lock est à 0 le processus peut rentré en SC et positionne


le lock à 1 grâce à l’instruction Tsl , il peut ensuite lire et écrire
dans la mémoire partagée

Quand il finit il doit remettre le lock à 0 pour permettre l’accès


aux autre
Afin d’utiliser le Tsl Rx Lock il est nécessaire de rajouter une
partie à notre code ( algorithme) comme suit :

Copier la valeur de lock dans le registre, et mettre lock à 1


Comparer l’ancienne valeur de lock à 0 :

◦ Si l’ancienne valeur différente de 0 un autre processus utilise déjà la


mémoire refaire le test jusqu'à ce que lock == 0

◦ Si non personne n’utilise la mémoire, le processus peut l’utiliser


Avant d’entrer en SC le processus fait un appelle : enter_region

Le processus est alors en attente active pour avoir un verrou libre (


lock)

Quand le verrou se libère le processus rentre en SC et exécute ses


instructions

Quand le processus fini il invoque leave_region qui libère le


verrou (lock=0)

Il est donc très important d’écrire les deux appels enter_region et


leave_region au bon moment dans le code !!
Une autre instruction similaire est le XCHG
Enter_region
MOVE REGISTER,#1 | mettre 1 dans le registre
XCHG REGISTER,LOCK | échange les contenus du registre et de lock
CMP REGISTER;#0 | lock était-elle à 0
JNE enter_region |si elle n’était pas à 0 boucle
RET | retourne à l’appelant : entre en section critique
Leave_region:
MOVE LOCK,#0 | stocke un 0 dans lock
RET | retourne à l’appelant
L’algorithme vérifie bien en EM si il y a au plus un processus dans
la SC, le processus qui rentre bloque tout les autres

L’algorithme respecte bien la condition d’absence d’inter-blocage,


deux processus qui veulent rentrer en même temps ne se bloque
pas mutuellement

La condition de progression est assuré, un processus hors SC ne


bloque pas les autres

L’attente borné est vérifier si un processus attend un temps fini


pour rentrer en SC, le processus actuellement en SC doit la
débloquer en sortant.
Plusieurs mécanismes peuvent réaliser l’EM par attente active,
tels que :

L’Alternance stricte

L’algorithme de Peterson
Il est question de faire passer les processus tour à tour ou en
alternance

Une variable turn vérifie le processus dont c’est le tour pour


avoir la SC

Supposant deux processus 0 et 1 qui souhaite rentrer en SC

Le processus qui a son numéro égale à la valeur de turn aura


accès à la SC
P0 P1
Fonctionnement:
P0 lit la valeur de turn, il trouve 0 et rentre en SC
P1 fait de même, turn étant à 0 il rentre en boucle en attente
que turn passe à 1

Quant P0 quitte la SC, il passe turn à 1, P1 détecte le


changement et rentre en SC

Si les deux processus ont des temps d’exécutions proches le


mécanisme d’alternance actif fonctionne bien
Problème:
Si P0 et P1 ont une vitesse d’exécution trop différente ( un
processus beaucoup plus lent que l’autre )

Supposant P0 beaucoup plus rapide que P1

P0 utilise la SC et laisse place à P1 avec turn =1

P1 étant lent n’utilise pas la SC avant que P0 ne la réclame à


nouveau

P0 va se retrouvé bloqué hors de la SC car turn =1


Spoule d’impression : Si la SC est protégé par le mécanisme
d’alternance que ce passe t’il ?

Cette solution contraint les deux processus à fonctionner de


manière strictement alterné

Un processus ne peut donc en aucun cas placer deux requêtes


consécutives
L’algorithme de Peterson a été développées en 1981 et est
considéré comme la première solution logiciel viable et
alternative à l’alternance stricte

L’algorithme de Peterson utilise deux variable, une pour


montrer l’intérêt du processus à entrer en SC et l’autre pour
indiqué à qui le tour

L’algorithme peut être utilisé pour plus de deux variables


contrairement a l’alternance stricte.
veut_entrer

L’algorithme est comme suit :


Initialisation
Di =false
Dj = false
Pi Pj

Di= true ; Dj= true ;


Tour = i; Tour = j;
While (Dj==true) && (Tour ==i) ;// While (Di==true) && (Tour ==j) ;//
attente active attente active
Section critique; Section critique;
Di = False; Dj = False;
Test de l’algorithme :

L’exclusion mutuelle est elle vérifier ?

On suppose Pi en SC => Di = true et Tour = i

Si Pj veut rentrer => Dj = true et Tour = j


Test condition : While (Di==true) && (Tour ==j) ;// attente active

Les deux condition sont vérifier, il va donc attendre que Pi finisse


l’exécution.

L’algorithme vérifie bien l’EM, il y a au plus un processus dans la SC


Absence de blocage (inter-blocage) ?

Un processus doit pouvoir entrer en SC si les deux sont en


attente
si Pj et Pi veulent rentrer Di et Dj passe à true, ensuite l’un des
deux aura tour pour lui, exemple tour = i

Pj va avoir la condition (tour = j) fausse et pourra rentrer

L’algorithme respecte bien la condition d’absence d’inter-


blocage
Condition de progression :

Supposons Pj hors SC ET Pi veut rentrer

Si Pj hors SC alors Dj = false donc Pi aura sa première


condition fausse et pourra rentrer

La condition de progression est assuré


Attente borné
Si Pi est dans la SC, Pj doit pouvoir y entrer après un temps
fini

Si Pi en SC => condition d’accès de Pj :


◦ While (Di==true) && (Tour ==j) ;// attente

Quand Pi va sortir de la SC il passe Di à false


La condition d’accès se débloque et Pj rentre en SC

L’attente borné est donc vérifier


Plusieurs mécanismes peuvent réaliser l’EM par attente
passive, tels que :

les verrous,

les sémaphores,

les moniteurs
les verrous: Un verrou v est une variable booléenne sur
laquelle deux opérations sont définies, Verrouille(v) et
Déverrouille(v).

Ce sont les deux seules opérations (mis à part la création et


sa destruction) qui peuvent manipuler le verrou.
Opération Verrouille(v):
Si un verrou v est initialisé à vrai et qu’un processus appelle Verrouille(v),
le verrou est positionné à faux.
Si un second processus appelle Verrouille(v), alors il passe à l’état bloqué
et joint la file d’attente associée à v.

void Verrouille(verrou v)
{
if v == 1;
◦ V=0
◦ Rentre en SC
else
suspendre le processus appelant dans la file associée à v
}
Opération Deverrouille(v):

S’il y a un processus en attente sur le verrou v, alors ce


processus est réactivé en le retirant de la file d’attente
associée à v pour joindre la file des processus prêts.

S’il n’y a pas de processus en attente pour obtenir le verrou v,


le verrou v est libéré en le positionnant à vrai (état initial).
void Deverrouille(verrou v)
{ if (la file associée à v est non vide)
débloquer un processus en attente dans file
else v = 1;}
Un verrou permet de résoudre le problème de l’EM à n
processus de manière simple.

Il suffit de verrouiller un verrou v avant d’entrer en SC,


bloquant ainsi les autres processus qui accèdent à leur SC
protégée par le même verrou v.

La sortie d’une SC se fait en déverrouillant v, ce qui libère le


verrou ou réveille un processus bloqué pour l’accès à sa SC
Initialisation globale: int v= 1;

Demande d’entrée en SC : verrouille (v)

Accès à la ressource : <SC>

Fin et Sortie de la SC : deverouille(v)


Inconvénient : problème du processus avec le temps d’exécution
qui finit

Un processus P1 lit le verrou et le trouve à 0, et se vois retirer le


temps CPU avant de le mettre à 1

Le processus P2 est exécuté, il lit verrou qui est encore à 0 et le


passe à 1 en rentrant dans la SC

Ensuite P1 est réveillé, il continue son exécution et rentre aussi en


SC !

On se retrouve avec 2 processus en SC


Exemple: utilisation d’un verrou pour la réservation d’une
place
Init V= 1
verrouille (v)
si nbplace > 0
alors
réserver une place;
nbplace = nbplace – 1;
Save
deverouille(v)
L’outil sémaphore:
Une autre solution est d’utiliser un outil de synchronisation
offert par le système d’exploitation : les sémaphores.

Un sémaphore SEM est une structure système composée


d’une file d’attente L de processus et d’un compteur K, appelé
niveau du sémaphore et contenant initialement une valeur val

Cette structure ne peut être manipulée que par trois


opérations P(sem), V(sem) et init(sem, val)
l’exécution de ces opérations s’effectue interruptions
masquées et ne peut pas être interrompue

Un outil sémaphore peut être assimilé à un distributeur de


jetons dont le nombre initial est fixé par l’opération init

L’acquisition d’un jeton par un processus donne le droit à ce


processus de poursuivre son exécution. Sinon, le processus
est bloqué.
L’opération init:
init a pour but d’initialiser le sémaphore : elle met à vide la file
d’attente L et initialise avec la valeur val le compteur K

init(sémaphore sem, entier val)


debut
masquer_it;
sem.K : = val;
sem.L : = vide;
démasquer_it;
fin
L’opération P (sem):
L’opération P(sem) attribue un jeton au processus appelant si
un jeton est disponible

Si pas de jeton il bloque le processus dans la file sem.L

L’opération P est donc une opération éventuellement


bloquante pour le processus élu qui l’effectue

Si blocage ré-ordonnancement et un nouveau processus prêt


est élu
Le compteur K du sémaphore est décrémenté d’une unité. Si
la valeur du compteur devient négative, le processus est
bloqué.
L’opération V (sem):
L’opération V(sem) a pour but de rendre un jeton au
sémaphore.

si il y a au moins un processus bloqué dans la file d’attente L


du sémaphore, un processus est réveillé

C’est le processus le plus anciennement endormi qui est


réveillé.
L’opération V est une opération qui n’est jamais bloquante
pour le processus qui l’effectue
Des cas particulier de sémaphores existe :

Les Mutex ou sémaphore binaire

Les sémaphores privés ou bloquant

Les sémaphores compteur


Les Mutex sont une version simplifier des sémaphores, ils
sont utilisé pour la gestion des EM et sont facile à implémenté

Un mutex est une variable qui peut avoir deux états


déverrouillé ou verrouillé

L’orsuqu’un thread ( process) veut entrer en SC il invoque


mutex_lock, si le mutex est libre il peut rentrer en SC

Si le mutex est verrouillé le thread est bloqué jusqu’à ce que


le thread dans la SC invoque mutex_unlock.
Utilisation des sémaphores Mutex:

La réalisation d’une section critique s’effectue en utilisant un


sémaphore mutex, dont le compteur K est initialisé à 1

Le prélude de la section critique correspond à une opération


P(mutex), qui correspond au mutex_lock

Le postlude de la section critique correspond à une opération


V(mutex), qui correspond au mutex_unlock
Bien que le mutex_lock soit comparable à enter_region , ce dernier
induit une boucle d’attente active qui peut être infini

Si c’est un processus qui est en boucle infini le système le stop


automatiquement après un moment (schéduler), par contre un
thread peut rester indéfiniment en boucle

mutex_lock est donc bien meilleur puisqu’il invoque thread_yield est


va donc passer la main à un autre thread

On trouve également dans certaines bibliothèque l’appele


mutex_trylock qui test la disponibilité de la SC avant de faire l’appel
mutex_lock
init (mutex, 1);
Réservation :
P(mutex); ou mutex_lock –– prelude de section critique
si nbplace > 0
alors
◦ reserver une place;
◦ nbplace = nbplace – 1;
fsi
V(mutex); ou mutex_unlock –– postlude de section critique
Pthreads fait appel au mutex pour gérer l’entré en SC, il utilise
les appels :

Pthread_mutex_init Crée un nouveau mutex

Pthread_mutex_destroy Détruit un mutex

Pthread_mutex_lock Verrouille ou bloque un mutex

Pthread_mutex_unlock Déverrouille un mutex


Les sémaphores privés ou bloquant

Permet au thread qui fait l’appel de ce sémaphore de s’autobloquer

Un thread est bloqué quand il doit attendre qu’une ressource se


libère, ou qu’une autre tâche s’exécute

Le thread va donc verrouiller un mutex bloquant, et attendre


qu’une variable de condition soit vérifier pour le débloquer

Les variables de condition sont sans mémoire, si un signal est


envoyé et que le thread n’ai pas en écoute, le signal est perdu.
Appel Pthread pour variable de condition :

Pthread_cond_init Crée une variable de condition

Pthread_cond_destroy Supprimer la variable de condition

Pthread_cond_wait Attend une variable de condition

Pthread_cond_signal Envoie un signal au thread en attente de condition

Pthread_cond_broadcast Diffuse un signal aux threads an attente


Allocation de n ressources:

On considère à présent que l’on a n sections critiques.

Le sémaphore res d’allocation de ressources est initialisé au


nombre d’exemplaires de ressources initialement disponibles

On fait correspondre un jeton par exemplaire de ressources


Acquérir un exemplaire de ressource est synonyme d’acquérir
le jeton correspondant, soit une opération P(res)
Rendre la ressource est synonyme de rendre le jeton associé,
soit une opération V(res)
Exemple du parking à N place gérer par un feu rouge
Si une voiture rentre => N-1
Si une voiture sort => N+1
On va crée un sémaphore initialisé à N :
Sémaphore parking initialisé à N
Prog vehicule
...
P(parking)
|...
V(parking)
...
Le P(parking) :

P(Park)
N= N- 1
si (N< 0) alors
◦ étatProcessus = Bloqué
◦ mettre processus en file d’attente
finSi
invoquer l’ordonnanceur

Tant qu’il y a encore de la place les voitures peuvent rentrer


Si N=0, la voiture attend ( feux rouge)
Le V(parking):

V(Park)
N= N+ 1
si (N<= 0) alors
◦ extraire processus de file d’attente
◦ étatProcessus = Prêt
finSi
invoquer l’ordonnanceur

Si une place se libère et qu’une voiture attend, on la laisse rentrer (


extraire de la file d’attente)
Les sémaphores sont utilisé dans les langages de
programmation et dans les systèmes d’exploitation qui
n’implémente pas de synchronisation

Bien que efficace il est courant de faire des erreurs de


programmation et d’oublié de libérer un sémaphore bloqué,
c’est pourquoi des méthodes de synchronisation plus poussé
sont utilisé tels que les Moniteurs
Pour améliorer la gestion des ressources critiques, Hoare et
Brinch hansen ont mis au point des mécanismes de
synchronisation de haut niveau appelé Moniteur

Un moniteur est une collection de procédures, variables et


structures de données regroupé dans un même module

Les processus peuvent évoquer n’importe quelle procédure du


moniteur, mais ne peuvent pas accéder aux structures de
données interne à partir de procédure externe
Une propriété importante des moniteurs est l’impossibilité
d’avoir deux processus qui sont actifs en même temps

Un moniteur est une structure de langage de programmation,


le compilateur voit un moniteur et gère les procédure d’un
moniteur différemment des autres appels

Les premières instruction d’un moniteur montre si le


processus appelant peut s’exécuter directement, ou si il doit
attendre qu’un processus déjà en exécution quitte le moniteur
L’utilisation des moniteurs se base sur les compilateurs pour
son fonctionnement

Une fois les sections critique convertis en moniteur, deux


processus ne pourront jamais exécuter une section critique en
même temps car le compilateur les gère directement.

Bien que la SC soit assurer, il faut pouvoir gérer les autres


processus en attente hors de cette SC
Afin de pouvoir s’assurer du bon fonctionnement il faut
bloquer le processus si la SC est utilisée ( mise en veille)

Utilisation de variables conditionnelles suite au opérations


Wait et Signal

Un processus qui a besoin d’une condition « Cond »pour


continuer aura un Wait de Cond, pendant ce temps la un autre
processus pourra rentrer en SC sera exécuté
Si par exemple le deuxième processus en exécution valide
Cond, il va envoyer un Signal sur la variable Cond pour réveiller
le premier processus bloqué

Un problème peut survenir, si P2 est en SC et il réveille P1, les


deux peuvent se retrouver en SC !

Trois approches sont utilisable


Dans la solution de Hoare, on laisse s’exécuter le processus
qui vient d’être réveillé et de suspendre l’autre

Pour Brinch Hansen le processus qui a envoyé le signal doit


tout de suite quitter le moniteur, cette solution est plus
simple à mettre en place

Il est enfin possible de laisser le processus qui envoie le signal


finir son exécution, et de continuer l’exécution du processus
réveillé dès la fin d’exécution de l’autre.
Les variable de condition n’ont pas de compteur ou de fil
d’attente

si un signal est envoyé il doit obligatoirement être attendu


par un processus, si non il sera perdu

Il faut impérativement faire un wait avant un signal


Tout les langage de programmation ne prennent pas en
charge les moniteurs comme le C
L’un des programme qui gère les Moniteur est Java

Java utilise le mot clé Synchronized en declarant une méthodes


qui va garantir que, un thread qui utilise cette méthode aura
l’exclusivité de son utilisation

Java ne prend pas en charge les variables de condition, elles


sont remplacer par des méthodes permettant de placer un
processus en sommeil.
Exemple du parking avec moniteur Monitor parking {
entier : compteur := 20;
condition : entrée;

procedure entrer {
if (compteur = 0) {
entrée.wait;
}
compteur := compteur - 1;
}

procedure sortie {
compteur := compteur + 1;
entrée.signal;
}
}
Bien que les moniteurs simplifie la programmation des SC, ils
ont besoin d’un langage qui les prennent en charge
nativement grâce à un compilateur qui connais le type
Moniteur

Les moniteurs ( et les sémaphores) sont développés pour


résoudre le problème de EM avec multiprocesseur et mémoire
partager, ils deviennent inutilisable sur un système
multiprocesseur où chaque CPU a ça propre mémoire.
http://deptinfo.unice.fr/~baude/PCR/Cours_ExcMut.pdf

Système d’exploitation, 3eme édition, Andrew tanenbaum.

Vous aimerez peut-être aussi