le problème les besoinslig-membres.imag.fr/.../cours/se/3a-synchroetd.pdf · © f. boyer, uga...

Post on 05-Jun-2020

0 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1© F. Boyer, UGA Cours de Programmation Concurrente – Info4

4. Mécanismes de base pour la synchronisation F. Boyer, Laboratoire Lig Fabienne.Boyer@imag.fr

■  Le problème■  Les besoins

◆  Exemple de l’application bancaire

■  Les solutions de base◆  Les Sections critiques◆  Les Verrous

2© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Le problème

processus ou threads concurrents

accès concurrents à des ressources partagées

incohérences potentielle

3© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Exemple

4© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Les sections critiques

■  Principe des sections critiques :

◆  On ne sait pas contrôler l’accès à une variable

◆  On peut contrôler l’accès aux instructions qui manipulent la variable, par ajout de code de contrôle

code de contrôle avant instructions de manipulation de variables partagées

code de contrôle après

Section Critique

5© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Sections critiques

■  Élement de synchronisation de base (E.W. Dijkstra)

Le code de contrôle du'une SC doit garantir que: ◆  Lorsqu’un processus est dans une SC, aucun autre ne peut être

dans la même SC

◆  Aucune hypothèse ne doit être faite sur les vitesses relatives des processus et sur le nombre de processeurs

◆  Pas de blocage intempestif

◆  Absence de privation

6© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Sections critiques

■  n threads: T0, T1, .., Tn

■  T0, T1, .., Tn manipulent un ensemble de variables partagées a, b, c, …

■  Structure d’un thread Ti :…<entry section> // code de contrôle avant<manipulation de a,b,c,..> // section critique<exit section> // code de contrôle après…

Remarque : le programmeur peut définir autant de sections critiques que d'ensemble de variables partagées

7© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Essai

Données partagées :int busy= false;

Ti (i=0..N):

while (busy); busy = TRUE;

<critical section>

busy = FALSE;

8© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Algorithme de Dekker (1965)

Données partagées : int turn = 0; int flag[2] = {false, false};

Ti ( i = 0 ou 1) :

flag[i] = TRUE; while (flag[1-i]) { // the other wants to enter if (turn == 1-i) { // it isn't my turn flag[i] = FALSE; while (turn != i); // att. active flag[i] = TRUE; } } <critical section> turn = 1 – i; flag[i] = FALSE;

à Non généralisable à n processus / threads (n > 2)à Non FIFO

9© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Algorithme de Peterson (1981)

Données partagées : int last = 0; int interested[2] = {FALSE, FALSE};

Ti (i = 0 ou 1) :

interested[i] = TRUE; last = i; while (last == i && interested[1-i]) ; // attente active <critical section> interested[i] = FALSE;

Solution à 2 processus généralisable à n processus

10© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Algorithme de Lamport

Données partagées : int number[n+1] = {0,0,0,…}; int choosing[n+1];

Ti (i=0..N):

choosing[i] = TRUE; number[i] = 1 + max(number[0], …, number[n-1]); choosing[i] = FALSE; for (j=1; j<= n; j++) { while (choosing[j]); // wait until j gets a ticket while (number[j] != 0) && // wait while j tries entering if j has a higher prio ((number[j] < number[i]) || (number[j] == number[i]) && j<i))); } <critical section> number[i] = 0;

11© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Solutions

■  Logicielles◆  Complexes

◆  Pas vraiment efficaces

■  Matérielles◆  Masquage des IT◆  Usage de l’instruction Test&Set / Swap

12© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Mise en œuvre des SC par masquage des interruptions

■  Principe◆  Entry section : masquer les IT

◆  Exit section : restaurer les IT

■  Problèmes◆  Solution non utilisable en multiprocesseurs

◆  Temps passé en SC non contrôlable

■  Le masquage est acceptable en mono-processeur si la durée d'exécution du code masqué est courte

13© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Instruction Test&Set (multiprocesseurs)

■  Teste et modifie le contenu d’un mot mémoire de manière atomique (non interruptible)

Equivalent fonctionnel en langage C:

int Test&Set (int *b) { // set b to true, and return initial value of b int res = *b; *b = TRUE; return res; }

14© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Instruction Test&Set

Données partagées : int busy = FALSE;

Pi : … while (Test&Set (&busy)); <critical section> busy = FALSE; …

à  Attente activeà  Risque de privationà  Utiliser un système de ticket pour éviter la

privation

15© F. Boyer, UGA Cours de Programmation Concurrente – Info4

+Instruction Test&Set

typedef struct { int dist_ticket;

int clock; int busy;

} lock;

void initLock(lock *lock){ lock->dist_ticket=0; lock->clock=0;

lock->busy = FALSE; }

void enter(lock *lock){ int my_ticket; while (test&set(&lock->busy))); my_ticket = lock->dist_ticket++; release(&(lock->busy)); while (my_ticket != lock->clock);

} void exit(lock *lock){

while (test&set(&lock->busy))); lock->clock++; release(&(lock->busy));

}

à Allouer un ticket pour éviter la privation

takes a ticket

16© F. Boyer, UGA Cours de Programmation Concurrente – Info4

+Usage

lock l; int cpt = 0; T0: initlock(&l); <create T1 & T2>

T1: … lock (&l); cpt++; unlock(&l); … T2: … lock (&l); cpt++; unlock(&l); …

17© F. Boyer, UGA Cours de Programmation Concurrente – Info4

+Scenario avec T1, T2 et T3

init(&l);T3: enter(&l) ……………………………………..T3: exec SC……………………...………............T1: enter(&l) – loop on while(my_ticket..)…..T2: enter(&l) – loop on while(my_ticket ..).…T3: exit(&l)………………………………………..T1: exec SC………………………………………T1: exit(&l)……………………………………….T2: exec SC……………………………..............T2: exit(&l)………………………………………..

ticket T3

ticket T1

ticket T2

clock

00 00 00 1 00 1 2 0

1 2 11 2 1

2 22 2

3

18© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Instruction Swap

■  Swap : permutation atomique de deux variables.

void Swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; }

19© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Solution à base d’attente passive

■  Problème des solutions précédentes : ◆  gaspillage de l’UC (attente active)

■  Principes des solutions à base d’attente passive :◆  Endormir un processus lorsque la section est

verrouillée◆  Le réveiller lorsqu’elle se libère

à Utilisation de deux primitives fournies par le noyau :à  suspend(queue q) et wakeup()

20© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Principes de mise en œuvre des fonctions Suspend et Wakeup

Données partagées proc_ctxt current; proc_ctxt_list ready_queue; void suspend( proc-ctxt_list *queue) { proc_ctxt *old = current; mask(); put_last(queue, current); current= get_first(ready_queue); ctxt_swap(current, old); unmask(); }

void wakeUp(proc_ctxt *p){ mask(); put_last(ready_queue, p); unmask(); }

21© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Les verrous

■  Un verrou est un élément de synchronisation qui ne laisse passer qu’un processus à la fois

■  Généralement à base d’attente passive◆  Sauf pour les spin-locks

■  S’utilise au travers d’une interface◆  lock() // ou enter()◆  unlock() // ou exit()

■  Différentes mise en œuvres à différentes propriétés◆  Verrous de base : utilisation d’une primitive matérielle de synchronisation +

attente passive◆  Sémaphores initialisées à 1◆  Moniteurs / sections critiques conditionnelles mono-condition

22© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Exemple d’usage d’un verrou

int alloc_id () {

lock(&l);

return id++;

unlock(&l);

}

// Données partagées

int id;

lock l;

void init() {

id= 0;

init(&l);

}

23© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Exemple de mise en œuvre d’un verrou

typedef struct {

int busy; // is the lock taken or free

proc_ctxt_list waitings; // waiting processes

} lock;

void init_lock(lock *l) {

mask();

l->busy = FALSE;

init_list(&(l->waitings));

unmask();

}

true

P3 P2

waitings

busy

lock

24© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Exemple de mise en œuvre d’un verrou

void lock(lock *l) {

mask();

if(l->busy)

suspend(&(l->waitings));

l->busy = TRUE;

unmask();

}

void unlock(lock *l) {

proc_ctxt w;

mask();

l->busy = FALSE;

if (w = get_first((&(l->waitings))))

wakeup(w);

unmask();

}

Risque de non-exclusion

25© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Exemple de mise en œuvre d’un verrou

void lock(lock *l) {

mask();

while (l->busy)

suspend(&(l->waitings));

l->busy = TRUE;

unmask();

}

void unlock(lock *l) {

proc_ctxt w;

mask();

l->busy = FALSE;

if (w = get_first((&(l->waitings))))

wakeup(w);

unmask();

}

Risque de privation (PROBLEME DU VOL DE CYCLE)

26© F. Boyer, UGA Cours de Programmation Concurrente – Info4

Exemple de mise en œuvre d’un verrou

void lock(lock *l) {

mask();

if (l->busy)

suspend(&(l->waitings));

l->busy = TRUE;

unmask();

}

void unlock(lock *l) {

proc_ctxt w;

mask();

if (w = get_first((&(l->waitings))))

wakeup(w);

else l->busy = FALSE;

unmask();

}

top related