ENS Cachan
Problématique Difficile de gérer la concurrence : Pas toujours facile d avoir des fonctions réentrantes. Risque de race condition : ex : x :=x+1 x :=x+1 On voudrait des blocs d instructions atomiques. Notion de région critique : enter critic() enter critic() x :=x+1 x :=x+1 exit critic() exit critic() Aujourd hui : comment faire enter critic() et exit critic()?
Problème de l exclusion mutuelle Garantir qu un seul thread est en région critique à la fois. Oui, mais... Quelques contraintes supplémentaires : Eviter un interblocage enter critic1() enter critic2() enter critic2() enter critic1() x :=x+1 x :=x+1 exit critic2() exit critic1() exit critic1() exit critic2() Question Comment éviter simplement ces interblocages de sections critiques répertoriées? Garantir équité, absence de famine si je demande, je pourrai (un jour) rentrer en section critique Notion subtile, quelles conditions sur les autres? Lien avec les jeux : pas de stratégie gagnante, si bloquer l autre=gagner, coalitions possibles,...
La synchronisation par verrou pthread_t tid[3] ; int compteur = 0 ; void *annexe(void *ordre) { int boucle ; for(boucle = 0 ; boucle < 10E30 ; boucle++){ compteur++ ; // section critique ici return NULL ; main() { [...] pthread_create(tid + {0,1,2, NULL, annexe, NULL) ; [...] printf("valeur de compteur à la fin : %d",compteur) ;
La synchronisation par verrou pthread_t tid[3] ; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER ; int compteur = 0 ; void *annexe(void *ordre) { int boucle ; for(boucle = 0 ; boucle < 10E30 ; boucle++){ pthread_mutex_lock(&mutex) ; compteur++ ; // section critique ici pthread_mutex_unlock(&mutex) ; return NULL ; main() { [...] pthread_create(tid + {0,1,2, NULL, annexe, NULL) ; [...] printf("valeur de compteur à la fin : %d",compteur) ;
Un exemple de problème : producteurs/consomateurs Données : un buffer de taille bornée méthodes add et get concurrentes et bloquantes méthode add 1)vérifier que le buffer n est pas plein......sinon attendre. 2) ajouter méthode get 1)vérifier que le buffer n est pas vide......sinon attendre. 2) enlever Analyse : section critique complexe, entrée dépend d une condition
Producteurs/consommateurs avec variables de condition int buffersize ; condition notfull, notempty ; mutex m ; Producteur void add(){ if (buffsize==maxbuf) wait(notfull) ; acquire(m) ; buffsize++ ; release(m) ; if (buffsize==1) signal(notempty) Consomateur void get(){ if (buffsize==0) wait(notempty) ; acquire(m) ; buffsize-- ; release(m) ; if (buffsize==maxbuf-1) signal(notfull)
Producteurs/consommateurs avec variables de condition int buffersize ; condition notfull, notempty ; mutex m ; Producteur void add(){ if (buffsize==maxbuf) wait(notfull) ; acquire(m) ; buffsize++ ; release(m) ; if (buffsize==1) signal(notempty) Consomateur void get(){ if (buffsize==0) wait(notempty) ; acquire(m) ; buffsize-- ; release(m) ; if (buffsize==maxbuf-1) signal(notfull) Problème : signal perdu si non attendu famine!
Les sémaphores Problématique Idée : utiliser un entier comme verrou. sémaphore s : entier 0 V(s) : incrémente s. P(s) : décrémente s bloquant. Question Quels sont les affichages possibles pour le programme suivant : init sem(s,2) ; P(s) ;P(s) ; P(s) ; P(s) ; print("a") ; print("b1") ; print("c1") ; print("b2") ; print("c2") ; V(s) ;V(s) ; V(s) ; V(s) ;
Producteurs/consommateurs avec semaphores Semaphores : la solution au signal perdu. semaphore bufferused =0 ; semaphore bufferfree =MAXSIZE ; Producteur void add(){ P(bufferfree) ; V(bufferused) Consomateur void get(){ P(bufferused) ; V(bufferfree)
Moniteurs de Hoare Problématique Définir l exclusion mutuelle dans une construction du programme Un moniteur est une entité qui contient des variables = ressources partagées en accès concurrent des procédures = méthodes en exclusion mutuelles des conditions synchronisation à la charge du compilateur. Un langage qui implémente les moniteurs : JAVA. static class our monitor { private int buff[3] ; public synchronized void rotate left(){wait() ;.. ; public synchronized void rotate right(){wait() ;.. ; public synchronized void set first(int i){buff[0]=i ; notify() public int get first(){..
Moniteurs de Hoare Problématique Définir l exclusion mutuelle dans une construction du programme Un moniteur est une entité qui contient des variables = ressources partagées en accès concurrent des procédures = méthodes en exclusion mutuelles des conditions synchronisation à la charge du compilateur. Un langage qui implémente les moniteurs : JAVA. static class our monitor { private int buff[3] ; public synchronized void rotate left(){wait() ;.. ; public synchronized void rotate right(){wait() ;.. ; public synchronized void set first(int i){buff[0]=i ; notify() public int get first(){..
Moniteurs de Hoare Problématique Définir l exclusion mutuelle dans une construction du programme Un moniteur est une entité qui contient des variables = ressources partagées en accès concurrent des procédures = méthodes en exclusion mutuelles des conditions synchronisation à la charge du compilateur. Un langage qui implémente les moniteurs : JAVA. static class our monitor { private int buff[3] ; public synchronized void rotate left(){wait() ;.. ; public synchronized void rotate right(){wait() ;.. ; public synchronized void set first(int i){buff[0]=i ; notify() public int get first(){..
Moniteurs de Hoare Problématique Définir l exclusion mutuelle dans une construction du programme Un moniteur est une entité qui contient des variables = ressources partagées en accès concurrent des procédures = méthodes en exclusion mutuelles des conditions synchronisation à la charge du compilateur. Un langage qui implémente les moniteurs : JAVA. static class our monitor { private int buff[3] ; public synchronized void rotate left(){wait() ;.. ; public synchronized void rotate right(){wait() ;.. ; public synchronized void set first(int i){buff[0]=i ; notify() public int get first(){..
Producteurs/consomateurs avec un moniteur de Hoare monitor ProdCons condition notfull, notempty ; integer count ; procedure add ; begin if count = N then wait(notfull) ; count := count+1 ; if count = 1 then signal(notempty) end procedure get ; begin if count = 0 then wait(notempty) ; count := count-1 ; if count = N-1 then signal(notfull) end end monitor ; Question Pourquoi cette solution marche, et pas celle avec des conditions?
Sans aide du système, comment écrire une entrée en section critique? Quelques (mauvaises) idées : désactivation des interruptions instruction TSL : enter = while(testandset(v,1)==1) (). exit = v=0 ; alternance stricte : while (v==1) () ; while (v==2) () ; critic1() ; critic2() ; v=2 ; v=1 ; Question En quoi ces solutions ne sont-elles pas complètement satisfaisantes?
Sans aide du système, comment écrire une entrée en section critique? Quelques (mauvaises) idées : désactivation des interruptions sécurité système, multiprocesseur instruction TSL : enter = while(testandset(v,1)==1) (). exit = v=0 ; attente active, multiprocesseur alternance stricte : while (v==1) () ; while (v==2) () ; critic1() ; critic2() ; v=2 ; v=1 ; nb threads connu, équité, attente active, multiprocesseur Question En quoi ces solutions ne sont-elles pas complètement satisfaisantes?
La solution de Peterson Comment faire un verrou sans instruction TSL? int turn ; int interested[2] ; void enter_critic(int pid){ turn = i ; interested[pid] = true ; while((turn==pid)&&(interested[1-pid])) ; void exit_critic(int pid){ interested[pid]=false ; Defaut : attente active, nb threads fixe.
Proble matique Me canismes de synchronisation Quelques proble mes classiques Le dı ner des philosophes Le proble me penser ou manger deux fourchettes pour manger pas de paroles pas d interblocage pas de famine Proble mes lie s a la concurrence
Lecteurs et rédacteurs. Le problème La ressource partagée : un texte. Plusieurs lecteurs peuvent y accéder en même temps. Si un rédacteur y accède, personne d autre n y accède. Pas d interblocage, pas de famine Question Si un lecteur accèdent immédiatement au texte dès qu aucun rédacteur n y accède, où est le problème?
Le coiffeur endormi Le problème Un salon de coiffure Un thread coiffeur Des threads clients Salle d attente avec N chaises Client attend, si pas possible repart Si personne, le coiffeur s endort.
Pour aller plus loin... Comment prouver rigoureusement que des algorithmes multithreads sont corrects? La modélisation par automates : on modélise le programme par un automate (graphe de contrôle), la composition parallèle est le produit asynchrone des automates, on regarde des propriétés sur le langage reconnu (par exemple, pour l équité, on aura souvent une condition de Buchi). Les invariants de resource On doit le préserver entre l entrée et la sortie de section critique. Les interférences et le rely-guarantee On fait l hypothèse de toutes les instructions qui peuvent interférer à tout moment, et on garantit qu on fera au plus telles instructions. Circularité de l implication : x y y x x y