Chap. 7

Chap. 7 Chap. 7 - Start

2017-05-07 63K 63 0 0

Description

1. Synchronisation de Processus . (ou de threads, fils ou tâches). Chapitre 7. http://w3.uqo.ca/luigi/. Le problème. Chap. 7. 2. Chap. 7. 3. Problèmes avec concurrence = parallélisme. Les threads concurrents doivent parfois partager données (fichiers ou mémoire commune) et ressources. ID: 545704 Download Presentation

Embed code:
Download Presentation

Chap. 7




Download Presentation - The PPT/PDF document "Chap. 7" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.



Presentations text content in Chap. 7

Slide1

Chap. 7

1

Synchronisation de Processus (ou de threads, fils ou tâches)

Chapitre 7

http://w3.uqo.ca/luigi/

Slide2

Le problème

Chap. 7

2

Slide3

Chap. 7

3

Problèmes avec concurrence = parallélisme

Les threads concurrents doivent parfois partager données (fichiers ou mémoire commune) et ressources

On parle donc de threads

coopérants

Si l’accès n’est pas contrôlé, le résultat de l’exécution du programme pourra

dépendre de l’ordre d’entrelacement

de l’exécution des instructions (

non-déterminisme

).

Un programme pourra

donner des résultats différents et parfois indésirables

de fois en fois

Slide4

Chap. 7

4

Exemple 1

Deux threads exécutent cette même procédure et partagent la même base de données

Ils peuvent être interrompus n’importe où Le résultat de l ’exécution concurrente de P1 et P2 dépend de l`ordre de leur entrelacementSouvent bon, parfois mauvais

M. X demande une

réservation d’avion

Base de données dit que fauteuil A est disponible

Fauteuil A est assigné à X et marqué occupé

Slide5

Chap. 7

5

Vue globale d’un «mauvais»entrelacement

M. Guy demande uneréservation d’avion Base de données dit que fauteuil 30A est disponibleFauteuil 30A est assigné à Guy et marqué occupé

M. Leblanc demande une réservation d’avion Base de données dit que fauteuil 30A est disponibleFauteuil 30A est assigné à Leblanc et marqué occupé

Interruption

ou retard

P1

P2

Slide6

Hypothèse de partage de données

Chap. 7

6

Partagées

entre threads

Les données partagées ne sont pas souvegardées quand on change de thread

Slide7

Cas pratique:

Deux threads qui mettent à jour un seul compteur d’accès à une page webExécuter en parallèle avec lui-même le code suivant:Quel pourrait être le résultat final dans a?

Exemple 2

Chap. 7

7

b=a

b++

a=b

Slide8

Chap. 7

8

b=a

b++

a=b

b=a

b++a=b

P1

P2

Supposons que a soit 0 au début

P1 travaille sur

son propre b

donc le résultat final sera a=1.Mais il y aura des cas où le résultat sera correct!?

interruption

Deux opérations en parallèle

var

a partagée

entre thread

var

b est privée

à chaque thread

Slide9

Chap. 7

9

3ème exemple

Thread P1

static char a;void echo(){ cin >> a; cout << a;}

Thread P2static char a;void echo(){ cin >> a; cout << a;}

Si la var a est partagée, le premier a est effacé

Si elle est privée, l’ordre d’affichage est renversé

Slide10

Asynchronie des threads

Quand plusieurs threads exécutent en parallèle, nous ne pouvons pas faire d’hypothèses sur la vitesse d’exécution des threads, ni leur entrelacementPeuvent être différents à chaque exécution du programmeDont le non-déterminisme

Chap. 7

10

Slide11

Chap. 7

11

Autres exemples

Des threads qui travaillent en simultanéité sur une matrice, par ex. un pour la mettre à jour, l`autre pour en extraire des statistiques

Problème qui affecte le programme du

tampon borné

, v. manuel

Slide12

Exercice

Dans un langage de programmation qui supporte la progr. parallèle, écrire un programme avec deux boucles en parallèleUne boucle ne fait qu’afficher des AUne autre boucle ne fait qu’afficher des BÀ l’écran, vous devriez voir des A et des Bs parsemés de manière aléatoirePour voir bien ce résultat il pourrait être nécessaire d’inclure un ‘retard’ dans chaque boucleSinon, dépendant de l’ordonnanceur, vous pourriez voir p.ex. 1000 fois A avant de voir le premier BP.ex. en Java utiliser méthode Tread.sleep ce qui n’est pas très facile, voir aide dans le wwwCeux qui réussissent à faire ceci, SVP venez me voir …

Chap. 7

12

Slide13

Chap. 7

13

Section Critique

Partie d’un processus dont l’exécution ne doit

pas

entrelacer

avec autres processus

Indivisibilité

de la section critique

Une fois qu’un processus ou fil y entre, il faut lui permettre de terminer cette section sans permettre à autres de jouer sur les mêmes données

La section critique doit être

verrouillée afin de devenir indivisible

Slide14

Entrelacement de threads A et B

Chap. 7

14

A

A Contin.

A Contin.

B

B contin

Les flèches indiquent délais ou interruptions

Beaucoup de possibilités, selon les points où A et B sont interrompus

Slide15

Indivisibilité de threads A et B par effet du verrou

Chap. 7

15

A

B

A

B

OU

Seulement deux possibilités,

quand chacun est exécuté sans interruptions

Slide16

Section critique verrouillée:

contrôler que ceci évite le pb

Chap. 7

16

M. X demande uneréservation d’avion Base de données dit que fauteuil A est disponibleFauteuil A est assigné à X et marqué occupé

indivisible

Slide17

Chap. 7

17

Le « mauvais » entrelacement n’est pas possible

M. Guy demande une

réservation d’avion

Base de données dit que fauteuil 30A est disponibleFauteuil 30A est assigné à Guy et marqué occupé

M. Leblanc demande une réservation d’avion Base de données dit que fauteuil 30A est occupé

P1

P2

Slide18

Chap. 7

18

Le problème de la section critique

Lorsqu’un thread manipule une donnée (ou ressource) partagée avec autres, nous disons qu’il se trouve dans une section critique (associée à cette donnée) Le problème de la section critique est de trouver un algorithme d`exclusion mutuelle de threads dans l`exécution de leur CritSect afin que le résultat de leurs actions ne dépendent pas de l’ordre d’entrelacement de leur exécution (avec un ou plusieurs processeurs)L’exécution des sections critiques doit être mutuellement exclusive et indivisible: à tout instant, un seul thread peut exécuter une CritSect pour une donnée (même lorsqu’il y a plusieurs UCT)Ceci peut être obtenu en plaçant des instructions spéciales dans les sections d`entrée et sortieImplantation du cadenas

Slide19

Chap. 7

19

Deux simplifications

Pour simplifier, parfois nous ferons l’hypothèse qu’il n’y a qu’une seule CritSect dans un thread

Et nous ne ferons plus distinction entre CritSect pour différentes données

Slide20

Chap. 7

20

Structure d’un programme type

Le programme est présenté comme boucle infinie: while(true)Chaque thread doit donc demander une permission avant d’entrer dans une CritSectLa section de code qui effectue cette requête est la section d’entréeLa section critique est normalement suivie d’une section de sortie (leave CritSect)Le code qui reste est la section non-critique

while (true) { enterCritSect CritSect leaveCritSect nonCritSect}

indivisible

Slide21

Chap. 7

21

Application (un programme qui répète à jamais)

M. X demande uneréservation d’avion enterCritSectBase de données dit que fauteuil A est disponibleFauteuil A est assigné à X et marqué occupéleaveCritSect

Section critique

Slide22

Chap. 7

22

Exigences pour solutions valides (*)

Exclusion MutuelleEn tout moment, au plus un thread peut être dans une CritSectDéroulementUne CritSect ne sera donnée qu’à un thread qui attend d’y entrerChaque fois qu’une CritSect devient disponible, s’il y a des threads qui l’attendent, un d’eux doit être capable d’y entrer (pas d’interblocage)Attente bornée Un thread qui attend d’entrer dans une CritSect pourra enfin y entrer (pas de famine)= aucun thread ne peut être exclu à jamais de la CritSect à cause d’autres threads qui la monopolisentNotez la différence entre interblocage et famine(*) Définitions plus compliquée dans le manuel, mais selon moi sans besoin

Slide23

Chap. 7

23

Trois types de solutions

Solutions par logicieldes algorithmes qui n’utilisent pas d`instruction spécialesSolutions fournies par le matériels’appuient sur l’existence de certaines instructions (du processeur) spécialesSolutions fournies pas le SEprocure certains appels du système au programmeurToutes les solutions se basent sur l’indivisibilité de l’accès à la mémoire centrale: une adresse de mémoire ne peut être affectée que par une instruction à la fois, donc par un thread à la fois. Plus en général, toutes les solutions se basent sur l’existence d’instructions indivisibles, qui fonctionnent comme Sections Critiques de base

Slide24

Solutions par logiciel pur

Chap. 7

24

Slide25

Un groupe d’étudiants collabore sur un devoir

Solution 1: Ils se passent la copie du devoir dans un ordre fixe: Marc, Ahmed, Marie, Marc, Ahmed, Marie …

Chap. 7

25

Slide26

Un groupe d’étudiants collabore sur un devoir

Solution 1: Ils se passent la copie du devoir dans un ordre fixe: Marc, Ahmed, Marie, Marc, Ahmed, Marie …Solution 2:Un étudiant passe la copie à un autre seulement si l’autre demande d’y travailler

Chap. 7

26

Slide27

Un groupe d’étudiants collabore sur un devoir

Solution 1: Un étudiant passe la copie au prochain dans un ordre fixe: Marc, Ahmed, Marie, Marc, Ahmed, Marie …Solution 2:Un étudiant passe la copie à un autre seulement si l’autre veut y travaillerSolution 3: Combiner les idées des solutions précédentes

Chap. 7

27

Slide28

Chap. 7

28

Solutions par logiciel(pas pratiques, mais intéressantes pour comprendre le pb)

Nous considérons d’abord 2 threads

Algorithmes 1 et 2 ne sont pas valides

Montrent la difficulté du problème

Algorithme 3 est valide

(algorithme de Peterson)

Notation

Débutons avec 2 threads: T0 et T1

Lorsque nous discutons de la tâche Ti,

Tj

sera toujours l’autre tâche (i != j)

while

(X){A}

:

repète

A tant que X est vrai

while(X)

: attend

tant

que

X

est

vrai

Slide29

Chap. 7

29

Idée de l’algorithme 1

Les threads se donnent mutuellement le tour

T0

T1T0T1…

Réalise l’exclusion mutuelle, mais viole l’exigence du déroulement:

Une CritSect pourra être donnée à des threads qui n’en ont pas besoin

P.ex. après T0, T1 pourrait n’avoir pas besoin d’entrer

Slide30

Chap. 7

30

Algorithme 1: threads se donnent mutuellement le tour

La variable partagée tour est initialisée à 0 ou 1La CritSect de Ti est exécutée ssi tour = iTi est actif à attendre si Tj est dans CritSect. Fonctionne pour l’exclusion mutuelle! Mais exigence du déroulement pas satisfaite car l’exécution des CritSect doit strictement alterner

Thread Ti:while(true){ while(tour!=i); CritSect tour = j; nonCritSect}

T0T1T0T1… même si l’un des deux n’est pas intéressé du tout

Rien faire

Slide31

Chap. 7

31

Thread T0:

While(true){ while(tour!=0); CritSect tour = 1; nonCritSect}

Thread T1:While(true){ while(tour!=1); CritSect tour = 0; nonCritSect}

Algorithme 1 vue globale

Initialisation de tour à 0 ou 1

Rien faire

Slide32

Chap. 7

32

Exemple: supposez que tour=0 au début

Thread T0: while(tour!=0); // premier à entrer CritSect tour = 1; nonCritSect while(tour!=0); // entre quand T1 finit CritSect tour = 1; nonCritSect etc...

Thread T1:while(tour!=1); // entre quand T0 finit CritSect tour = 0; nonCritSectwhile(tour!=1); // entre quand T0 finit CritSect tour = 0; nonCritSect etc...

Slide33

Chap. 7

33

Généralisation à n threads

Chaque fois,

avant qu’un thread puisse

rentrer

dans la section critique, il lui faut attendre que

tous les autres

aient eu cette chance!

En claire contradiction avec l’exigence de déroulement

Supposez le cas de 1 000 threads, dont seulement quelques uns sont actifs

Slide34

Algorithme 2

L’algorithme 2 prend en compte la critique à l’algorithme 1:Donne la CritSect seulement aux threads qui la veulentCependant on ne peut pas permettre à un processus de se redonner systématiquement la CritSec  famineFaut que chaque processus qui veut entrer donne une chance à des autres avant d’y entrer

Chap. 7

34

Slide35

Chap. 7

35

Algorithme 2 ou l’excès de courtoisie...

Une variable Booléenne par Thread: veut[0] et veut[1]Ti signale qu’il désire exécuter sa CritSect par: veut[i] =vraiMais il n’entre pas si l’autre est aussi intéressé!Exclusion mutuelle okDéroulement pas satisfait:Considérez la séquence:T0: veut[0] = vraiT1: veut[1] = vraiChaque thread attendra indéfiniment pour exécuter sa CritSect: interblocage

Thread Ti:while(true){ veut[i] = vrai; while(veut[j]); CritSect veut[i] = faux; nonCritSect}

 

            

            

rien faire

Slide36

Chap. 7

36

Thread T0:

while(true){

veut[0] = vrai; while(veut[1]); CritSect veut[0] = faux; nonCritSect}

Thread T1:while(true){ veut[1] = vrai; while(veut[0]); CritSect veut[1] = faux; nonCritSect}

Algorithme 2 vue globale

T0: veut[0] = vrai

T1: veut[1] = vrai

interblocage!

Après vous, monsieur

Après vous, monsieur

Slide37

Chap. 7

37

Algorithme 3 (dit de Peterson): bon! combine les deux idées: veut[i]=intention d’entrer; tour=à qui le tour

Initialisation: veut[0] = veut[1] = faux tour = i ou jDésir d’exécuter CritSect est indiqué par veut[i] = vraiveut[i] = faux à la sortie

Thread Ti:while(true){ veut[i] = vrai; // je veux entrer tour = j; // je donne une chance à l’autre while (veut[j] && tour==j); CritSect veut[i] = faux; nonCritSect}

Slide38

Chap. 7

38

Entrer ou attendre?

Thread Ti attend si:L’autre veut entrer est c’est le tour à l’autreveut[j]==vrai et tour==jUn thread Ti peut entrer si:L’autre ne veut pas entrer ou c’est la chance à luiveut[j]==faux ou tour==i

Utiliser la logique Booléenne pour contrôler

Slide39

Chap. 7

39

Thread T0:while(true){ veut[0] = vrai; // T0 veut entrer tour = 1; // T0 donne une chance à T1 while (veut[1]&&tour=1); CritSect veut[0] = faux; // T0 ne veut plus entrer nonCritSect}

Thread T1:while(true){ veut[1] = vrai; // T1 veut entrer tour = 0; // T1 donne une chance à 0 while (veut[0]&&tour=0); CritSect veut[1] = faux; // T1 ne veut plus entrer nonCritSect}

Algorithme de Peterson vue globale

Slide40

Initialisations possibles

Afin qu’un premier processus puisse entrer dans CritSec, il faut que le testveut[j]==faux ou tour==isoit vrai la première fois pour un des deux processus.Voici une possibilité:veut[0]=veut[1]=faux //initialisationMaintenant, si T1 ne fait rien, veut[1] reste faux et T0 peut entrerExercice: Étudier les autres possibilités pour le début.

Chap. 7

40

Slide41

Chap. 7

41

Scénario pour le changement de contrôle

Thread T0: … CritSect veut[0] = faux; // T0 ne veut plus entrer …

Thread T1: … veut[1] = vrai; // T1 veut entrer tour = 0; // T1 donne une chance à T0 while (veut[0]&&tour=0) ; //test faux, entre (F&&V) …

T1 donne une chance à T0 mais T0 a dit qu’il ne veut pas entrer.T1 entre donc dans CritSect

Slide42

Chap. 7

42

Autre scénario de changem. de contrôle

Thread T0: CritSect veut[0] = faux; // T0 ne veut plus entrer nonCritSect veut[0] = vrai; // T0 veut entrer tour = 1; // T0 donne une chance à T1 while (veut[1]==vrai&& tour=1) ; // test vrai, n’entre pas (V&&V)

Thread T1: veut[1] = vrai; // T1 veut entrer tour = 0; // T1 donne une chance à T0 // mais T0 annule cette action while (veut[0]&&tour=0) ; //test faux, entre (V&&F)

T0 veut rentrer mais est obligé à donner une chance à T1, qui entre

Slide43

Chap. 7

43

Mais avec un petit décalage, c’est encore T0!

Thread T0: CritSect veut[0] = faux; // 0 ne veut plus entrer nonCritSect veut[0] = vrai; // 0 veut entrer tour = 1; // 0 donne une chance à 1 // mais T1 annule cette action while (veut[1] && tour=1) ; // test faux, entre (V&&F)

Thread T1: veut[1] = vrai; // 1 veut entrer tour = 0; // 1 donne une chance à 0 while (veut[0]&&tour=0); // test vrai, n’entre pas

Si T0 et T1 tentent simultanément d’entrer dans CritSect, seule une valeur pour tour survivra:

non-déterminisme

(on ne sait pas qui gagnera), mais l’exclusion fonctionne

Slide44

Chap. 7

44

N’oblige pas une tâche d’attendre pour d’autres qui pourraient ne pas avoir besoin de la CritSect

Supposons que T0 soit le seul à avoir besoin de la CritSect, ou que T1 soit lent à agir: T0 peut rentrer de suite (veut[1]==faux la dernière fois que T1 est sorti) veut[0] = vrai // prend l’initiative tour = 1 // donne une chance à l’autre while veut[1] && tour=1 // veut[1]=faux, test faux, entre CritSect veut[0] = faux // donne une chance à l’autre

Cette propriété est désirable, mais peut causer

famine

pour T1 s’il est lent (condition de course, race condition)

Slide45

Hypothèse de fond

Dans des ordis avec plusieurs UCTs, il est nécessaire de supposer que seulement une UCT à la fois puisse exécuter les affectations aux variables veut et tour, ainsi que le testPendant qu’un thread ou processus fait accès à une adresse de mémoire, aucun autre ne peut faire accès à la même adresse en même temps

Chap. 7

45

Slide46

Chap. 7

46

Algorithme 3: preuve de validité (pas matière d’examen, seulement pour les intéressés…)

Exclusion mutuelle est assurée car:

T0 et T1 sont tous deux dans CritSect seulement si tour est simultanément égal à 0 et 1 (impossible)

Démontrons que déroulement est satisfaits:

Ti ne peut pas entrer dans CritSect seulement si en attente dans la boucle while avec condition: veut[j] == vrai et tour = j.

Si Tj ne veut pas entrer dans CritSect alors veut[j] = faux et Ti peut entrer dans CritSect

Slide47

Chap. 7

47

Algorithme 3: preuve de validité (cont.)

Si Tj a effectué veut[j]=vrai et se trouve dans le while, alors tour==i ou tour==j

Si

tour==i, alors Ti entre dans CritSect.

tour==j alors Tj entre dans CritSect mais il fera veut[j] =faux à la sortie: permettant à Ti d’entrer CritSect

mais si Tj a le temps de faire veut[j]=true, il devra aussi faire tour=i

Puisque Ti ne peut modifier tour lorsque dans le while, Ti entrera CritSect après au plus une entrée dans CritSect par Tj (attente limitée)

Slide48

Différence importante

Qelle est la différence importante entre Algo 1 et 3?Avec l’Algo 1, tous les processus (interessés ou non) doivent entrer et sortir de leur SC en tourViolation de l’exigence de déroulementAvec l’Algo 3, les procs qui ne sont pas intéressés laissent veut = faux et sont libres de faire autres choses

Chap. 7

48

Slide49

Exemple d’algorithme fautif

Thread Ti:while (true) { veut[i] = vrai; // je veux entrer tour = j; // je donne une chance à l’autre do while (veut[i] && tour==j); SC veut[i] = faux; SR}

Cette solution implémente correctement la SCUn seul proc à la fois peut entrerMais elle viole le déroulementveut[i] = faux n’affecte pas Tj car Tj ne teste pas veut[i] Tj doit attendre que Ti fasse tour=j après qu’il a fait tour=i, ce qui pourrait ne jamais se vérifier

Chap. 7

49

Slide50

Chap. 7

50

A propos de l’échec des threads

Si une solution satisfait les exigences d’ExclMutuelle et déroulement, elle procure une robustesse face à l’échec d’un thread dans sa nonCritSect

un thread qui échoue dans sa nonCritSect est comme un thread qui ne demande jamais d’entrer...

Par contre, situation difficile si un thread échoue dans la CritSect

un thread Ti qui échoue dans sa CritSect n’envoie pas de signal aux autres threads: pour eux Ti est encore dans sa CritSect...

solution: temporisation. Un thread qui a la SC après un certain temps est interrompu par le SE

Slide51

Chap. 7

51

Extension à >2 threads

L ’algorithme de Peterson peut être généralisé au cas de >2 threads

http://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1778&context=cstech

Cependant, dans ce cas il y a des algorithmes plus élégants, comme

l’algorithme du boulanger

, basée sur l’idée de ‘prendre un numéro au comptoir’...

Pas le temps d’en parler …

Slide52

Chap. 7

52

Une leçon à retenir…

Afin que des threads avec des variables partagées puissent réussir, il est nécessaire que tous les threads impliqués utilisent le même algorithme de coordination

Un protocole commun

Slide53

Chap. 7

53

Critique des solutions par logiciel

Difficiles à programmer! Et à comprendre!

Les solutions que nous verrons dorénavant sont toutes basées sur l’existence d’instructions spécialisées, qui facilitent le travail.

Les threads qui requièrent l’entrée dans leur

CritSect

sont

actifs à attendre-

busy

waiting

; consommant ainsi du temps de processeur

Situation de

scrutation

(polling)

Pour de longues sections critiques, il serait préférable de

bloquer

les threads qui doivent attendre...

Et de les

interrompre

quand ils peuvent entrer

Rappel: scrutation ou interruption

Slide54

Solutions par matériel

Chap. 7

54

Slide55

Chap. 7

55

Solutions matérielles: désactivation des interruptions

Si plusieurs UCT: exclusion mutuelle n’est pas préservéeOn ne peut pas désactiver les interruptions sur toutes les UCT en même tempsDonc pas bon en général

Thread Pi:

while(true){

désactiver interrupt

CritSect

rétablir interrupt

nonCritSect

}

Slide56

Chap. 7

56

Solutions matérielles: instructions machine spécialisées

Normal: pendant qu’un thread ou processus fait accès à une adresse de mémoire, aucun autre ne peut faire accès à la même adresse en même temps

Extension: instructions machine exécutant

plusieurs

actions (ex: lecture et écriture) sur la même case de mémoire de manière

indivisible

Une instruction indivisible ne peut être exécutée que

par un thread à la fois

(même en présence de plusieurs processeurs)

Slide57

Chap. 7

57

L’instruction test-and-set

Une version C de test-and-set:

Un algorithme utilisant testset pour Exclusion Mutuelle:Variable partagée b est initialisée à 0Le 1er Pi qui met b à 1 entre dans CritSectLes autres trouvent b à 1, n’entrent pas

bool testset(int& i){ if (i==0) { return true; i=1; } else { return false; }}

Tâche Pi: while testset(b)==false ; CritSect //entre quand vrai instructions critiques . . . b=0; //sortie de CS nonCritSect

Instruction indivisible!

Slide58

Chap. 7

58

Quand un proc Pi cherche d’entrer:

Si la SC est occupée,

i=1,

testset

(b)=faux et Pi reste en attente

Si la SC est libre,

i=0, il est tout de suite mis à 1 mais

testset

(b)=vrai et Pi peut entrer

Slide59

Chap. 7

59

L’instruction test-and-set (cont.)

Exclusion mutuelle est assurée: si Ti entre dans

CritSect

, l’autre

Tj

est

actif à attendre

Problème: utilise encore

actif à attendre

Scrutation ou polling

Peut

impléementer

l’exclusion mutuelle mais nécessite algorithmes plus complexes pour satisfaire les autres exigences du problème de la section critique

Lorsque Ti sort de

CritSect

, la sélection du

Tj

qui entrera dans

CritSect

est arbitraire:

pas de limite sur l’attente

: possibilité de

famine

Slide60

Chap. 7

60

Instruction ‘Échange’ (Swap)

Certains

UCTs

(ex: Pentium) offrent une instruction

xchg

(

a,b

) qui

interchange

le contenue de a et b de manière

indivisible

.

Mais

xchg

(

a,b

) souffre des même problèmes que test-and-set

Slide61

Chap. 7

61

Utilisation de xchg pour exclusion mutuelle

(Stallings)

Variable partagée b est initialisée à 0Chaque Ti possède une variable locale k Le Ti pouvant entrer dans CritSect est celui qui trouve b=0Ce Ti exclut tous les autres en assignant b à 1Quand CritSect est occupée, k et b seront 1 pour un autre thread qui cherche à entrerMais k est 0 pour le thread qui est dans la CritSect

Thread Ti:while(true){ k = 1 while k!=0 xchg(k,b); CritSect xchg(k,b); nonCritSect}

usage:

indivisible

Slide62

Sémaphores avec attente occupée

Chap. 7

62

Slide63

Chap. 7

63

Solutions basées sur des instructions fournies par le SE (appels du système)

Les solutions vues jusqu’à présent sont difficiles à programmer

On voudrait aussi qu`il soit plus facile d’éviter des erreurs communes, comme interblocages, famine, etc.

Besoin d’instruction à plus haut niveau

Les méthodes que nous verrons dorénavant utilisent des instructions puissantes, qui sont implantées par des appels au SE (system calls)

Slide64

Chap. 7

64

Sémaphores

Un sémaphore S est un entier qui, sauf pour l'Initialisation, est accessible seulement par ces 2 opérations

indivisibles et mutuellement exclusives:

acquire

(S)

release(S)

Il est partagé entre tous les threads qui s`intéressent à la même

CritSect

Les sémaphores seront présentés en deux étapes:

sémaphores qui sont actifs à attendre

Scrutation

sémaphores qui utilisent interruptions et files d ’attente

Slide65

Chap. 7

65

Spinlocks d’Unix-Linux: Sémaphores occupés à attendre (busy waiting)

La façon la plus simple d’implanter les sémaphores.Utiles pour des situations où l’attente est brève, ou il y a beaucoup d’UCTsS est un entier initialisé à une valeur positive, afin qu’un premier thread puisse entrer dans la CritSectQuand S>0, jusqu’à S threads peuvent entrerQuand S=0, aucun ne peut entrerS ne peut jamais être négatif

acquire(S):

while S==0 ;

S--; release(S): S++;

Attend si no. de threads qui peuvent entrer = 0

Augmente de 1 le no des threads qui peuvent entrer

Slide66

Chap. 7

66

Indivisibilité

Acquire: La séquence test-décrément est indivisible mais pas la boucle!Release est indivisible. Rappel: les sections indivisibles ne peuvent pas être exécutées simultanément par différent threads (ceci peut être obtenu en utilisant un des mécanismes précédents)

S == 0

indivisible

S - -

F

V

CritSect

IMPORTANT

Slide67

Chap. 7

67

Indivisibilité de acquire, release

S == 0

indivisible

S - -

F

V

S++

La boucle peut être interrompue pour permettre à un autre thread d’interrompre l’attente quand l’autre thread sort de la CritSect

interruptible

autre thr.

CritSect

CritSect

(Autre thread)

Slide68

Chap. 7

68

Thread T1: while(true){ acquire(S); CritSect release(S); nonCritSect}

Thread T2:while(true){ acquire(S); CritSect release(S); nonCritSect}

Semaphores: vue globale

Initialise S à

>

=1

Peut être facilement généralisé à plus. threads

Slide69

Chap. 7

69

Utilisation des sémaphores pour sections critiques

Initialiser S à 1Alors 1 seul thread peut être dans sa CritSectPour permettre à k threads d’exécuter CritSect, initialiser S à k

Thread Ti:

while(true){

acquire(S);

CritSect

release(S);

nonCritSect

}

Slide70

Chap. 7

70

Utilisation des sémaphores pour mettre des threads en seq.

On a 2 threadsP1 dans le premier thread doit être exécuté avant P2 dans le deuxièmeDéfinissons deux sémaphores S et TInitialisons S à 1, T à 0

P1

P2

acquire(S)

P1;

release(T)

acquire(T);

P2

Slide71

Famine possible avec les sémaphores spinlocks

Un thread peut n’arriver jamais à exécuter car il ne teste jamais le sémaphore au bon moment

Chap. 7

71

Slide72

Chap. 7

72

Interblocage

avec les sémaphores

Interblocage

: Supposons S et Q initialisés à 1Ils seront 0 au deuxième acquireAucun des deux procs ne peut avancer

T0 T1 acquire(S) acquire(Q) acquire(Q) acquire(S)

Slide73

Chap. 7

73

Sémaphores: observations

Quand S >= 0:Le nombre de threads qui peuvent exécuter acquire(S) sans devenir bloqués = SS threads peuvent entrer dans la CritSectPuissance par rapport aux mécanismes précédentsDans les solutions où S peut être >1 il faudra avoir un 2ème sém. pour les faire entrer un à la fois (excl. mutuelle)Quand S devient > 1, le thread qui entre le premier dans la CritSect est le premier à tester S (choix aléatoire) Famine possibleCeci ne sera plus vrai dans la solution suivante

acquire(S):while S==0 ; S--;

Slide74

Chap. 7

74

Comment éviter l’attente occupée et le choix aléatoire dans les sémaphores

Quand un thread doit attendre qu’un sémaphore devienne plus grand que 0, il est mis dans une file d’attente de threads qui attendent sur le même sémaphore

Les files peuvent être PAPS (FIFO), avec priorités, etc. Le SE contrôle l`ordre dans lequel les threads entrent dans leur CritSect

acquire

et

release

sont des appels au système

comme les appels à des opérations d’E/S

Il y a une file d ’attente pour chaque sémaphore comme il y a une file d’attente pour chaque unité d’E/S

Slide75

Sémaphores avec files d’attente

Chap. 7

75

Slide76

Chap. 7

76

Sémaphores avec file d’attente

Un sémaphore S devient une structure de données:S.value: Une valeur: nombre de processus pouvant entrerS.list Une liste d’attenteacquire(S): Si S=0 bloque thread qui effectue l’opération et l’ajoute à la liste S.listrelease(S) enlève (selon une politique juste, ex: PAPS/FIFO) un thread de S.list et le place sur la liste des threads prêts/ready.un tel sémaphore peut être associé à une liste d’attente comme un disque, une imprimante, etc.S>0 est un événement qu’un processus doit attendre

Slide77

Chap. 7

77

Implementation

(les

boîtes représentent des séquences indivisibles)

acquire(S): S.value --; si S.value < 0 { // CritSect occupée, thread doit attendre ajouter ce thread à S.list; block // thread mis en état attente (wait) } si S.value ≥ 0, continuer le thread release(S): S.value ++; si S.value  0 { // des threads attendent enlever thread P from S.list; wakeup(P) // thread choisi devient prêt }

S.value doit être initialisé à une valeur non-négative (dépendant de l’application, v. exemples)

Slide78

Chap. 7

78

Figure montrant la relation entre le contenu de la file et la valeur de S

(la séquence montrée n’est pas contigüe)

S > 0: n threads peuvent entrerS  0: aucun thread ne peut entrer et le nombre de threads qui attendent sur S est = |S|

Stallings

Slide79

Chap. 7

79

acquire et release contiennent elles mêmes des CritSect!

Les opérations

acquire

et

release

doivent être exécutées de manière indivisible (un seul

thr

. à la fois)

Pour ça, nous devons utiliser un des mécanismes vus avant

instructions spéciales: test-and-set

L’attente occupée dans ce cas ne sera pas trop onéreuse car

acquire

et

release

sont courts

Slide80

Exercice

Avec cette solution, on peut effectivement éviter la famine!Expliquez pourquoi et comment

Chap. 7

80

Slide81

Chap. 7

81

Problèmes classiques de synchronisation

Tampon borné (producteur-consommateur)

Écrivains - Lecteurs

Les philosophes mangeant

Slide82

Application: Tampon borné ou producteur-consommateur

Chap. 7

82

Slide83

Chap. 7

83

Le pb du producteur - consommateur

Un problème classique dans l ’étude des threads communicants

un thread

producteur

produit des données (p.ex.des enregistrements d ’un fichier) pour un thread

consommateur

Slide84

Chap. 7

84

Tampons de communication

Prod

Cons

1 donn

Prod

Cons

1 donn

1 donn

1 donn

Si le tampon est de longueur 1, le producteur et consommateur doivent forcement aller à la même vitesse

Des tampons de longueur plus grandes permettent une certaine indépendance. P.ex. à droite le consommateur a été plus lent

Slide85

Chap. 7

85

Le tampon borné (bounded buffer)une structure de données fondamentale dans les SE

b

[0]

b[1]

b[7]

b[2]

b[6]

b[3]

b[4]

b[5]

ou

out

: 1ère pos. pleine

in

: 1ère pos. libre

b

[0]

b[1]

b[7]

b[2]

b[6]

b[3]

b[4]

b[5]

in

: 1ère pos. libre

out

: 1ère pos. pleine

bleu: plein, blanc: libre

Le tampon borné se trouve dans la mémoire partagée entre consommateur et usager

Slide86

Chap. 7

86

Pb de sync entre threads pour le tampon borné

Étant donné que le prod et le consommateur sont des threads indépendants, des problèmes pourraient se produire en permettant accès simultané au tampon

Les sémaphores peuvent résoudre ce problème

Slide87

Chap. 7

87

Sémaphores: rappel

Soit S un sémaphore sur une CritSectil est associé à une file d ’attenteS > 0 : S threads peuvent entrer dans CritSectS = 0 : aucun thread ne peut entrer, aucun thread en attenteS < 0 : |S| thread dans file d ’attenteacquire(S): S - -si avant S > 0, ce thread peut entrer dans CritSectsi avant S <= 0, ce thread est mis dans file d ’attenterelease(S): S++si avant S < 0, il y avait des threads en attente, et un thread est réveillé si avant S >= 0 un proc de plus pourra entrerIndivisibilité de ces ops

Slide88

Pensez à un petit entrepôt de caisses d’un produit

Ceux qui veulent y apporter une caisse, doivent avant tout savoir s’il y a de l’espace Un sémaphore E dit combien d’espace dispo: Producteur peut entrer si et seulement si il y en a Ceux qui veulent en retirer des caisses, doivent avant tout savoir s’il y en a à retirerUn sémaphore F qui dit combien de caisses disponibles:Consommateur peut entrer si et seulement si il y en aPour éviter la confusion, une seule personne peut y travailler à un moment donnéUn sémaphore M dit s’il y a quelqu’un dans l’entrepôtOccupé ou libre

Chap. 7

88

Slide89

Chap. 7

89

Autrement dit …

Un sémaphore

E

pour synchroniser producteur et consommateur sur le

nombre d’espaces libres

Un sémaphore

F

pour synchroniser producteur et consommateur sur le

nombre d’éléments consommables

dans le tampon

Un sémaphore

M

pour

exclusion mutuelle

sur l’accès au tampon

E et F ne

font pas l’

ExMut

Slide90

Chap. 7

90

Solution de P/C: tampon circulaire fini de dimension k

Initialization: M.count=1; //excl. mut. F.count=0; //esp. pleins E.count=k; //esp. vides

Producteur:while(true){ produce v; acquire(E); acquire(M); ajouter(v); release(M); release(F);}

Consommateur:while(true) acquire(F); acquire(M); retirer(); release(M); release(E); consume(w);}

Sections Critiques

ajouter(v):

b[in]=v; In ++ mod k;

retirer(): w=b[out]; Out ++ mod k; return w;

Slide91

Chap. 7

91

Points intéressants à étudier

Dégâts possibles en inter changeant les instructions sur les sémaphores

ou en changeant leur initialisation

Généralisation au cas de plus. prods et cons

Slide92

Chap. 7

92

Concepts importants de cette partie du Chap 7

Le problème de la section critique

L’entrelacement et l’indivisibilité

Problèmes de famine et

interblocage

Solutions logiciel

Instructions matériel

Sémaphores occupés ou avec files

Fonctionnement des différentes solutions

L’exemple du tampon borné

Par rapport au manuel: ce que nous n’avons pas vu en classe vous le verrez au

lab

Slide93

Chap. 7

93

Glossaire

Indivisible, atomique

, non-interruptible

:

Ces mots sont équivalents

Le mot atomique est utilisé dans son sens original grec: a-

tomos

= indivisible

Faut pas se faire dérouter par le fait que les atomes dans la physique moderne sont divisibles en électrons, protons, etc. …

La définition précise de ces concepts est un peu compliquée, et il y en a aussi des différentes… (faites une recherche Web sur ces mot clé)

Ce que nous discutons dans ce cours est un concept intuitif: une séquence

d’ops

est indivisible ou

atomique

si elle est exécutée toujours du début à la fin sans aucune interruption ni autres séquences en parallèle

Slide94

Chap. 7

94

Non-déterminisme et conditions de course

Non-déterminisme: une situation dans laquelle il y a plusieurs séquences d’opérations possibles à un certain moment, même avec les mêmes données. Ces différentes séquences peuvent conduire à des résultats différentsConditions de course: Les situations dans lesquelles des activités exécutées en parallèle sont ‘en course’ les unes contre les autres pour l`accès à des ressources (variables partagées, etc.), sont appelées ‘conditions de course ’L’ordre des accès détermine le résultat

Slide95

Chap. 7

95

Thread, processus

Les termes thread, process, sont presque équivalents dans ce contexte

Tout ce que nous avons dit au sujet de threads concurrent est aussi valable pour processus concurrents

Slide96

Chap. 7

96

Différents noms pour acquire, release

Acquire, release ont eté appelés des noms différents

Leur inventeur (Dijkstra) les appelait P, V (provenant de mots en Hollandais …)

D’autres auteurs les appellent

wait

,

signal

Etc.

Slide97

Chap. 7

97

Sémaphores binaires

Un type particulier

de sémaphore

Dans les sémaphores binaires, la variable ne peut être que 0 ou 1

P.ex. le sémaphore S dans le producteur-consommateur est binaire

On a prouvé en théorie que tout

pb

de synchro peut être résolu utilisant seulement des sémaphores binaires, v. manuel

Slide98

Chap. 7

98

Difficulté des problèmes de synchronisation

Les problèmes et solutions qui se trouvent dans l’étude du parallélisme et de la répartition sont entre les plus complexes de l’informatique

Car les programmes parallèles ont un comportement mutuel imprévisible dans le temps

Beaucoup de concepts complexes de math, physique etc. peuvent entrer en considération

Heureusement, les langages de programmation comme Java nous cachent cette complexité

Mais pas complètement … les systèmes répartis sont sujets à des pannes imprévisibles

dues à des conditions de temporisation non prévues

Slide99

Parallélisme dans la programmation fonctionnelle

Dans la programmation fonctionnelle, le parallélisme vient naturel sans besoin d’artifices:y = g(f(x,y), h(z))Pour calculer y, la fonction g lance en parallèle les fonctions f et h qui n’ont pas besoin de communiquer l’une avec l’autreCependant la programmation purement fonctionnelle est peu utilisée pour des raisons pratiques

Chap. 7

99


About DocSlides
DocSlides allows users to easily upload and share presentations, PDF documents, and images.Share your documents with the world , watch,share and upload any time you want. How can you benefit from using DocSlides? DocSlides consists documents from individuals and organizations on topics ranging from technology and business to travel, health, and education. Find and search for what interests you, and learn from people and more. You can also download DocSlides to read or reference later.