Synchronisation Classique

Slides:



Advertisements
Présentations similaires
Module Systèmes d’exploitation
Advertisements

Synchronisation de Processus
Calculs de complexité d'algorithmes
La classe String Attention ce n’est pas un type de base. Il s'agit d'une classe défini dans l’API Java (Dans le package java.lang) String s="aaa"; // s.
Module Systèmes d’exploitation
Module Systèmes dexploitation Chapitre 6 Communication Interprocessus Partie III École Normale Supérieure Tétouan Département Informatique
GEF 435 Principes des systèmes d’exploitation
Hiver 2005Maj JGA Beaulieu & Capt MWP LeSauvage GEF 243B Programmation informatique appliquée Considération de temps.
GEF 435 Principes des systèmes dexploitation Communication Interprocessus (CIP) II (Tanenbaum 2.3)
GEF 435 Principes des systèmes dexploitation Communication Interprocessus (CIP) III (Tanenbaum 2.3)
GEF 243B Programmation informatique appliquée
Synchronisation des Processus
1 UMLV 1. Introduction 2. Hachage ouvert 3. Hachage fermé 4. Implémentation des fonctions Méthodes de hachage.
Conception et programmation Programmation Parallèle
Chapitre 3 Coopération et synchronisation par variables partagées
Chapitre 2 Processus & Threads
Exécutif Temps réel. Limitation des système classiques Rappels Mise en œuvre lourde des communications entre processus Problème de prédictibilité avec.
1 Efficient Data and Program Integration Using Binding Patterns Ioana Manolescu, Luc Bouganim, Francoise Fabret, Eric Simon INRIA.
Introduction à la POO: Les classes vs les objets
Parallel Programming in C with MPI and OpenMP
Principes de programmation (suite)
44 Contrôle du déroulement du programme. 4-2 Objectifs A la fin de ce cours, vous serez capables de : Utiliser les constructions de prise de décision.
Rappel sur la synchronisation des processus
Synchronisation et communication entre processus
Atomicité Transactions Atomiques Recouvrement à Base de Journal
La fonction alloue un bloc de taille size. Il faut indiquer la taille du bloc que lon veut allouer. Le premier exemple: #include void main()
Processus Concept de Processus Ordonnancement de Processus
Les tris.
Introduction au paradigme objet Concepts importants surcharge (overload) redéfinition (override) Définition d’une classe Définition des attributs.
77 Utilisation des classes (suite). 7-2 Objectifs A la fin de ce cours, vous serez capables de : Définir des méthodes surchargées dans une classe Fournir.
Classes abstraites et Interfaces
Master 1 SIGLIS Java Lecteur Stéphane Tallard Chapitre 5 – Héritage, Interfaces et Listes génériques.
5.1 URDL22005 Systèmes dexploitation Threads Vue dEnsemble Modèles de Multithreading Problèmes des Threads Pthreads Threads Windows XP Threads Linux Threads.
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
66 Utilisation des classes et des objets. 6-2 Objectifs A la fin de ce cours, vous serez capables de : Créer de nouvelles classes à laide de Eclipse Utiliser.
8.1 URDL22005 Systèmes dexploitation Interblocages Modèle Système Caractérisation dinterblocage Méthodes pour Gérer les Interblocages Prévention des Interblocages.
Module 51 Module 5 - Synchronisation de Processus (ou threads, ou fils ou tâches) Module 5 - Synchronisation de Processus (ou threads, ou fils ou tâches)
Les itérations (boucle) Les routines Les Fonctions
Programmation concurrente
CSI2520, Hiver 2007 Programmation concurrente. CSI2520, Hiver 2007 Programmation concurrente La programmation est distribuée lorsque les processus ne.
Chapitre 6 (Silberchatz)
Contrôle de types Les types en programmation Expressions de types Un contrôleur de types Equivalence de types Conversions de types Généricité.
IFT 6800 Atelier en Technologies d’information
LIFI-Java 2004 Séance du Jeudi 9 sept. Cours 1. La notion de langage Décrire une tâche à effectuer –programme Écrire à un haut niveau –facile pour lutilisateur.
Synchronisation de Processus (ou threads, ou fils ou tâches)
Partie II Sémantique.
COURS DE PROGRAMMATION ORIENTEE OBJET :
CSI 1502 Principes fondamentaux de conception de logiciels
Introduction à Linda Béat Hirsbrunner References Nicholas Carriero, David Gelernter : "Linda in context", Communications of ACM, vol. 32 (n° 4, April 1989)
Chapitre 6 : Synchronisation des processus et des fils
99 Réutilisation du code grâce à l'héritage. 9-2 Objectifs À la fin de ce cours, vous serez capables de : Définir l'héritage Utiliser l'héritage pour.
Répéter dans un programme avec une Instruction itérative
Synchronisation de Processus
Exemple de gestion d'un buffer clavier en liste circulaire
Structures des données
Le langage C Structures de données
1 Notations Asymptotiques Et Complexité Notations asymptotiques : 0 et  Complexité des algorithmes Exemples de calcul de complexité.
Ch. PAUL - Piles et Files à l'aide de listes chainées
Gérer la sécurité des mots de passe et les ressources
LES PILES ET FILES.
Gestion de processus Corrigé TD 1 EFREI I
Chapitre 6.2 Les curseurs Cours SGBD 3A Mme hkimi Jihène
Créer des packages.
Interactions entre Processus
Tutorat en bio-informatique
La programmation système
Programmation Système et Réseau
Conception de Programmes - IUT de Paris - 1ère année – Cours 8 – Les entrées/sorties Comment fonctionnent les opérateurs > pour les types élémentaires.
Pthread Ordonnancement. #define _MULTI_THREADED #include #ifndef _CHECK_H #define _CHECK_H /* headers used by a majority of the example program */ #include.
Systèmes d’exploitation Processus conclusion Modèle conceptuel de processus Pour masquer les effets des interruptions, les SE fournissent un modèle conceptuel.
Transcription de la présentation:

Synchronisation Classique Contexte Le problème de la section critique Matériel pour la synchronisation Sémaphores Problèmes classiques de synchronisation

Contexte 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.

Race 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; }

Race 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; }

Race 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}

Solution 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ée Supposer que chaque processus exécute à une vitesse différente de 0 Pas d’hypothèses concernant les vitesses d’exécution relatives des processus

Solution 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);

Thread Travailleur while (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 }

Algorithme 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?

Algorithme 1 // Thread 0 turn = TURN0; void enteringCriticalSection(int t) { while (turn != t) laisser_la_main(); } void leavingCriticalSection(int t) { turn = 1 - t;

Algorithme 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?

Algorithme 2 void enteringCriticalSection(int t) { { flag0 = true; while(flag1 == true) laisser_la_main(); } void leavingCriticalSection(int t) flag0 = false;

Algorithme 3 Combine les 2 idées précédentes Règles respectées?

Algorithme 3 // Thread 0 void leavingCriticalSection(int t) 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;

Maté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

Structures de Données pour Solutions Matérielles typedef struct { boolean data; } HardwareData; boolean get(HardwareData *var) { return var->data; } void set(HardwareData *var, boolean data) { var->data = data;

Structure de Données pour Solutions Maté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);

Thread 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(); }

Thread 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(); }

Sé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++;

Sémaphore comme Outil de Synchronisation Gé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

Synchronisation avec Sémaphores Semaphore sem; // initialisé à 1 while (true) { acquire(sem); // section critique release(sem); // section non critique }

Implé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;

Implé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

Deadlock 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.

Problèmes Classiques de Synchronisation Problème du Tampon Borné (Bounded Buffer) Problème des Lecteurs/Ecrivains Problème des Philosophes

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

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); }

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; }

Problème du Tampon Borné:Producteur Objet *message; while (true) { // des instructions diverses … // produire l’item & insérer dans le tampon message = produireMessage(); insert(message); }

Problème du Tampon Borné:Consommateur Objet *message; while (true) { // instructions diverses … // consommer un item du tampon message = remove(); }

Problème Lecteurs-Ecrivains: Lecteur RWLock 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); }

Problème Lecteurs-Ecrivains: Ecrivain RWLock db; while (true) { acquireWriteLock(db); // on a un accès en écriture // écrire releaseWriteLock(db); }

Lecteurs-Ecrivains: Base de Données typedef struct { int readerCount; // initialisé à 0 Semaphore mutex; // initialisé à 1 Semaphore db; // initialisé à 1 } RWLock;

Lecteurs-Ecrivains: Méthodes Lecteur void 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) { --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);

Lecteurs-Ecrivains: Méthodes Ecrivain void acquireWriteLock() { acquire(&verrou.db); } void releaseWriteLock() { release(&verrou.db);

Problème des Philosophes Données partagées Semaphore *baguettes[5];

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(); }

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