7a.1 URDL22005 Systèmes dexploitation Synchronisation Classique Contexte Le problème de la section...
-
Upload
josce-leclere -
Category
Documents
-
view
110 -
download
0
Transcript of 7a.1 URDL22005 Systèmes dexploitation Synchronisation Classique Contexte Le problème de la section...
7a.1 URD L2 2005Systèmes d’exploitation
Synchronisation ClassiqueSynchronisation Classique
Contexte
Le problème de la section critique
Matériel pour la synchronisation
Sémaphores
Problèmes classiques de synchronisation
7a.2 URD L2 2005Systèmes d’exploitation
ContexteContexte
Accès concurrent à une mémoire partagée peut produire des incohérences
Maintenir la cohérence des données requière des mécanismes pour assurer une exécution correcte des processus coopérants
Une solution mémoire partagée au problème de tampon borné (bounded buffer) contient un problème de “race condition” (condition de concurrence) sur la variable donnée count.
7a.3 URD L2 2005Systèmes d’exploitation
Race ConditionRace Condition
Le Producteur appelle
while (1) {
while (count == BUFFER_SIZE)
; // operation nulle
// ajouter un element au tampon
count++;
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
}
7a.4 URD L2 2005Systèmes d’exploitation
Race ConditionRace Condition
Le Consommateur appelle
while (1) {
while (count == 0)
; // operation nulle
// retirer un element du tampon
count--;
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
}
7a.5 URD L2 2005Systèmes d’exploitation
Race ConditionRace Condition
count++ peut être implémenté de la façon suivante
register1 = count register1 = register1 + 1 count = register1
count– peut être implémenté de la façon suivante
register2 = count register2 = register2 - 1 count = register2
Considérez cette exécution:
S0: producteur exécute register1 = count {register1 = 5}S1: producteur exécute register1 = register1 + 1 {register1 = 6} S2: consommateur exécute register2 = count {register2 = 5} S3: consommateur exécute register2 = register2 - 1 {register2 = 4} S4: producteur exécute count = register1 {count = 6 } S5: consommateur exécute count = register2 {count = 4}
7a.6 URD L2 2005Systèmes d’exploitation
Solution au Problème de Section CritiqueSolution au Problème de Section Critique
1. Exclusion Mutuelle – Si le processus Pi est dans sa section critique, alors aucun autre processus ne peut exécuter sa section critique
2. Progression – S’il n’y a aucun processus dans la section critique et que des processus veulent entrer dans leur section critique, alors la sélection des processus pour entrer en section critique ne peut pas être retardée indéfininement
3. Attente Bornée - Une borne doit exister sur le nombre de fois que les autres processus sont permis d’entrer dans leur section critique après qu’un processus ait fait une requête d’admission en section critique et avant que cette demande ne soit accordéeSupposer que chaque processus exécute à une vitesse différente
de 0
Pas d’hypothèses concernant les vitesses d’exécution relatives des processus
7a.7 URD L2 2005Systèmes d’exploitation
Solution pour 2 TâchesSolution pour 2 Tâches
2 Tâches, T0 et T1 (Ti et Tj)
3 solutions présentées. Toutes implémentent l’interface suivante:
const int TURN0 = 0; const int TURN1 = 1;
void enteringCriticalSection(int turn); void leavingCriticalSection(int turn);
7a.8 URD L2 2005Systèmes d’exploitation
Thread TravailleurThread Travailleurwhile (true) {
// initialisation des variables partagées
….
// demande d’entrée en section critique
enteringCriticalSection(id);
// section critique
...
// modification des varaibles partagées
...
// sortie de section critique
leavingCriticalSection(id);
// section NON critique
}
7a.9 URD L2 2005Systèmes d’exploitation
Algorithme 1Algorithme 1
Les threads partagent un entier turn
Si turn==i, thread i rentre dans sa section critique
Ne réspecte pas la règle de progession Pourquoi?
7a.10 URD L2 2005Systèmes d’exploitation
Algorithme 1Algorithme 1
// Thread 0turn = TURN0;
void enteringCriticalSection(int t) {
while (turn != t)
laisser_la_main();
}
void leavingCriticalSection(int t) {
turn = 1 - t;
}
}
7a.11 URD L2 2005Systèmes d’exploitation
Algorithme 2Algorithme 2
Ajouter plus d’informations sur l’état Drapeau boléen pour indiquer l’intérêt du thread pour entrer
dans la section critique
Règle de progression toujours pas respectée Pourquoi?
7a.12 URD L2 2005Systèmes d’exploitation
Algorithme 2Algorithme 2
void enteringCriticalSection(int t) {
{
flag0 = true;
while(flag1 == true)
laisser_la_main();
}
void leavingCriticalSection(int t)
{
flag0 = false;
}
7a.13 URD L2 2005Systèmes d’exploitation
Algorithme 3Algorithme 3
Combine les 2 idées précédentes
Règles respectées?
7a.14 URD L2 2005Systèmes d’exploitation
Algorithme 3Algorithme 3
// Thread 0
void enteringCriticalSection(int t) {
int other = 1 - t;
turn = other;
if (t == 0) {
flag0 = true;
while(flag1 == true && turn == other)
laisser_la_main();
}
void leavingCriticalSection(int t)
{
flag0 = false;
}
7a.15 URD L2 2005Systèmes d’exploitation
Matériel de SynchronisationMatériel de Synchronisation
Plusieurs systèmes fournissent un support matériel pour gérer des sections critiques
Uniprocesseurs – bloquer les interruptions Le code en exécution s’exécute sans préemption Générallement pas efficace sur des multiprocesseurs
OSs utilisant cette technique ne passent pas à l’échelle
Machines modernes fournissent des instructions spécifiques
Atomiques = non-préemptables Soit tester un mot mémoire et le modifier Ou échanger le contenu de deux mots mémoire
7a.16 URD L2 2005Systèmes d’exploitation
Structures de Données pour Solutions Structures de Données pour Solutions MatériellesMatérielles
typedef struct
{
boolean data;
} HardwareData;
boolean get(HardwareData *var) {
return var->data;
}
void set(HardwareData *var, boolean data) {
var->data = data;
}
7a.17 URD L2 2005Systèmes d’exploitation
Structure de Données pour Solutions Structure de Données pour Solutions Matérielles - contMatérielles - cont
boolean TestAndSet(HardwareData *var)
{
boolean oldValue = get(var);
set(var, true);
return oldValue;
}
void swap(HardwareData *this, HardwareData *other) {
boolean temp = get(this);
set(this, get(other));
set(other, temp);
}
7a.18 URD L2 2005Systèmes d’exploitation
Thread Utilisant TestAndSet VerrouThread Utilisant TestAndSet Verrou
// Verrou partagé par tous les threads
HardwareData verrou = { false };
while (true) {
while (TestAndSet(verrou))
laisser_la_main();
sectionCritique();
set(verrou, false);
sectionNonCritique();
}
7a.19 URD L2 2005Systèmes d’exploitation
Thread Utilisant Instruction swapThread Utilisant Instruction swap
// verrou partagé par tous les threads
HardwareData verrou = {false};
// chaque thread a une copie locale de clef
HardwareData clef = {true};
while (true) {
set(clef, true);
do {
swap(verrou, clef);
} while (get(clef) == true);
sectionCritique();
set(verrou, false);
sectionNonCritique();
}
7a.20 URD L2 2005Systèmes d’exploitation
SémaphoreSémaphore Outil de synchronisation ne provoquant pas du “busy waiting” (attente
active)(spin lock)
Semaphore S – entier Deux opérations standards modifient S: acquire() and release()
A l’origine (Hollandaise) appelées P() and V() Moins compliqué Peut être accédé via deux opérations indivisibles (atomiques)
acquire(S) {
while S <= 0
; // no-op
S--;
}
release(S) {
S++;
}
7a.21 URD L2 2005Systèmes d’exploitation
Sémaphore comme Outil de Synchronisation Sémaphore comme Outil de Synchronisation GénéralGénéral
Sémaphore de Comptage – valeur entière sur un domaine non restreint
Sémaphore Binaire – valeur entière 0 ou 1; plus simple à implémenter Connu aussi sous le nom de as verrou d’exclusion
Peut implémenter un sémaphore de comptage S avec des sémaphores binaires
Fournit l’exclusion mutuelle
7a.22 URD L2 2005Systèmes d’exploitation
Synchronisation avec SémaphoresSynchronisation avec Sémaphores
Semaphore sem; // initialisé à 1
while (true) {
acquire(sem);
// section critique
release(sem);
// section non critique
}
7a.23 URD L2 2005Systèmes d’exploitation
Implémentation SémaphoresImplémentation Sémaphores
acquire(S){
valeur--;
if (valeur < 0) {
ajouter processus à liste
bloquer;
}
}
release(S){
valeur++;
if (valeur <= 0) {
supprimer un processus P de liste
réveiller P;
}
}
7a.24 URD L2 2005Systèmes d’exploitation
Implémentation SémaphoresImplémentation Sémaphores
Doit garantir que deux processus ne puissent pas exécuter acquire() et release() simultanément sur un même sémaphore
Ainsi l’implémentation devient le problème de la section critique Peut maintenant avoir de l’attente active dans l’implémentation
de la section critique
Mais le code de l’implémentation est court
Très peu d’attente active si la section critique est très peu occupée
Les applications peuvent rester longtemps dans une section critique
Problèmes de performance discutés dans cette conférence
7a.25 URD L2 2005Systèmes d’exploitation
Deadlock et FamineDeadlock et Famine
Deadlock – deux ou plusieurs processus en attente infinie pour un évènement qui ne peut être provoqué que par un processus en attente
Soient S et Q deux sémaphores initialisés à 1
P0 P1
acquire(S); acquire(Q);
acquire(Q); acquire(S);
. .
. .
. .
release(S); release(Q);
release(Q); release(S);
Famine – blocage infini. Un processus peut ne jamais être repêché de liste des processus bloqués du sémaphore.
7a.26 URD L2 2005Systèmes d’exploitation
Problèmes Classiques de SynchronisationProblèmes Classiques de Synchronisation
Problème du Tampon Borné (Bounded Buffer)
Problème des Lecteurs/Ecrivains
Problème des Philosophes
7a.27 URD L2 2005Systèmes d’exploitation
Problème du Tampon BornéProblème du Tampon Borné
const int BUFFER_SIZE = 5;
Objet *buffer[BUFFER_SIZE];
int in, out; // initialisé à 0
Semaphore mutex; // initalisé à 1
Semaphore empty; // initialisé à BUFFER_SIZE
Semaphore full; // initialisé à 0
7a.28 URD L2 2005Systèmes d’exploitation
Problème du Tampon Borné:Méthode insert()Problème du Tampon Borné:Méthode insert()
void insert(Objet *item) {
acquire(empty);
acquire(mutex);
// ajouter un item au tampon
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
release(mutex);
release(full);
}
7a.29 URD L2 2005Systèmes d’exploitation
Problème du Tampon Borné:remove()Problème du Tampon Borné:remove()
Objet *remove() {
acquire(full);
acquire(mutex);
// supprimer un item du tampon
Objet *item = buffer[out];
out = (out + 1) % BUFFER SIZE;
release(mutex);
release(empty);
return item;
}
7a.30 URD L2 2005Systèmes d’exploitation
Problème du Tampon Borné:ProducteurProblème du Tampon Borné:Producteur
Objet *message;
while (true) {
// des instructions diverses
…
// produire l’item & insérer dans le tampon
message = produireMessage();
insert(message);
}
7a.31 URD L2 2005Systèmes d’exploitation
Problème du Tampon Borné:ConsommateurProblème du Tampon Borné:Consommateur
Objet *message;
while (true) {
// instructions diverses
…
// consommer un item du tampon
message = remove();
}
7a.32 URD L2 2005Systèmes d’exploitation
Problème Lecteurs-Ecrivains: LecteurProblème Lecteurs-Ecrivains: LecteurRWLock db;
while (true) {
// instructions diverses
...
acquireReadLock(db);
// on a maintenant un accès lecture à la base de données
// lire de la base de données
// relâcher le verrou
releaseReadLock(db);
}
7a.33 URD L2 2005Systèmes d’exploitation
Problème Lecteurs-Ecrivains: EcrivainProblème Lecteurs-Ecrivains: Ecrivain
RWLock db;
while (true) {
acquireWriteLock(db);
// on a un accès en écriture
// écrire
releaseWriteLock(db);
}
7a.34 URD L2 2005Systèmes d’exploitation
Lecteurs-Ecrivains: Base de DonnéesLecteurs-Ecrivains: Base de Données
typedef struct {
int readerCount; // initialisé à 0
Semaphore mutex; // initialisé à 1
Semaphore db; // initialisé à 1
} RWLock;
7a.35 URD L2 2005Systèmes d’exploitation
Lecteurs-Ecrivains: Méthodes LecteurLecteurs-Ecrivains: Méthodes Lecteurvoid acquireReadLock(RWLock verrou) {
acquire(&verrou.mutex);
++readerCount;
// si je suis le 1er à lire, dire aux autres
// que la base de données est en train d’être lue
if (readerCount == 1)
acquire(&verrou.db);
release(&verrou.mutex);
}
void releaseReadLock(RWLock verrou) {
acquire(&verrou.mutex);
--readerCount;
// si je suis le dernier à lire, dire aux autres
// que la base de données n’est plus lue
if (readerCount == 0)
release(&verrou.db);
release(&verrou.mutex);
}
7a.36 URD L2 2005Systèmes d’exploitation
Lecteurs-Ecrivains: Méthodes EcrivainLecteurs-Ecrivains: Méthodes Ecrivain
void acquireWriteLock() {
acquire(&verrou.db);
}
void releaseWriteLock() {
release(&verrou.db);
}
7a.37 URD L2 2005Systèmes d’exploitation
Problème des PhilosophesProblème des Philosophes
Données partagées
Semaphore *baguettes[5];
7a.38 URD L2 2005Systèmes d’exploitation
Problème des Philosophes (Cont.)Problème des Philosophes (Cont.)
Philosophe i:while (true) {
// prendre baguette de gauche
acquire(baguette[i]);
// prendre baguette de droite
acquire(baguette[(i+1)%5]);
manger();
// rendre baguette de gauche
release(baguette[i]);
// rendre baguette de droite
release(baguette[(i+1)%5]);
penser();
}
7a.39 URD L2 2005Systèmes d’exploitation
Problème des Philosophes (Cont.)Problème des Philosophes (Cont.)
• Début
• P(mutex)
• Si les deux voisins immédiats ne mangent pas Alors
• V(sémaphore privé)
• Etat = mange
• Sinon
• Etat = veut manger
• FSi
• V(mutex)
• P(sémaphore privé)
• mange ...
• Fin