TP 2 - Synchronisation de Threads

1/8
100%

Ecole Nationale des Sciences de lInformatique A. U. : 2014/2015

Syst mes dexploitation & Programmation Concurrente II2

TP 2 - Synchronisation de Threads

=======================================================

Exercice 1:

Un enseignant dinfo a pr vu faire un rattrapage pour ses groupes dans une salle de TP. Lunique salle de TP disponible peut contenir uniquement 10 tudiants. Cependant le nombre total des tudiants de ces groupes est gal 80. Pour cette raison, lenseignant sest trouv oblig de donner cette s ance de rattrapage plusieurs fois. Pour ce faire, il a utilis lalgorithme suivant : Lenseignant ouvre la porte, attend jusqu ce que la salle devienne pleine, ferme la porte, donne la s ance de rattrapage et ouvre la porte pour laisser sortir les tudiants. Par la suite, il r p te ce m me processus maintes fois jusqu ce que tous les tudiants aient assist la s ance de rattrapage. Evidemment, entre temps, certains tudiants doivent attendre leur tour pour acc der la salle de TP.

Nous allons mod liser ce sc nario avec un programme multithread . On suppose quil existe un thread enseignant et 80 threads tudiants. Ci-dessous, vous trouvez le thread enseignant impl ment en entier, et une partie du thread tudiant. Votre t che consiste terminer limpl mentation du thread tudiant.

Note : Pour terminer limpl mentation de ce thread, vous ne devez pas d clarer dautres variables. Par contre, vous pouvez ne pas utiliser toutes les variables d clar es dans le code ci-dessous. Nous supposons que les fonctions ouvrir\_porte(), fermer\_porte(), et enseigner() sont d finies et impl ment es quelque part ailleurs.

/\ Code \/

#define ETUDIANTS 80

#define CLASS 10

/\ D clarations ne pas modifier \/

int etudiants\_entrant = 0; /\ etudiants entrant la salle\/

int etudiants\_sortant = 0; /\ etudiants quittant la salle\/

sem\_t mutex1;

sem\_t mutex2;

sem\_t mutex3;

sem\_t entrer\_file;

sem\_t sortir\_file;

sem\_t tous\_entres;

sem\_t tous\_sortis;

/\ Ne rien modifier ici \/

int main()

{

pthread\_t tid, student\_tid ;

int i;

/\ initialize our semaphores \/

Publicité

sem\_init(&mutex1, 0, 0);

sem\_init(&mutex2, 0, 1);

sem\_init(&mutex3, 0, 1);

sem\_init(&entrer\_file, 0, 0);

sem\_init(&sortir\_file, 0, 0);

sem\_init(&tous\_entres, 0, 0);

sem\_init(&tous\_sortis, 0, 0);

pthread\_create(&tid, NULL, thread\_enseignant, NULL);

for (i = 0; i < ETUDIANTS; i++) {

pthread\_create(&student\_tid , NULL, thread\_etudiant, (void \*)i);

}

for (i = 0; i < ETUDIANTS; i++) {

pthread\_join(student\_tid , NULL);

}

printf("Cest tout.\n");

exit(0);

}

/\ thread\_enseignant ne rien modifier ici \/

void \thread\_enseignant(void \arg)

{

int i;

ouvrir\_porte();

while (1) {

for (i = 0; i < CLASS; i++) {

V(&entrer\_file);

}

P(&tous\_entres);

Publicité

Fermer\_porte();

enseigner();

ouvrir\_porte();

for (i = 0; i < CLASS; i++) {

V(&sortir\_file);

}

P(&tous\_sortis);

}

}

Question:

Compl tez le code pour la fonction thread\_etudiant() qui suit. Vous ne devez pas ajouter dautres variables mais vous pouvez ne pas utiliser certaines variables d clar es.

Note: Vous devez uniquement ajouter quelques lignes de code ici sans pour autant changer la structure de base de cette fonction.

R ponse:

void \thread\_etudiant(void \arg){

P(&entrer\_file); /\ Attendre une place \/

/\ entrer dans la salle \/

P(&mutex2); /\ Mutex pour students\_entering variable \/

etudiants\_entrant += 1;

if (etudiants\_entrant == CLASS) {

V(&tous\_entres); /\ last one in signals it's time to start class \/

etudiants\_entrant = 0;

}

V(&mutex2); /\ release lock for students\_entering variable \/

P(&sortir\_file); /\ wait to be told to leave \/

/\ Quitter la salle \/

P(&mutex3);/\ acquire lock for students\_exiting variable \/

etudiants\_sortant += 1;

Publicité

if (etudiants\_sortant == CLASS) {

V(&tous\_sortis); /\ last one out signals to let the next batch in \/

etudiants\_sortant = 0;

}

V(&mutex3); /\ release lock for students\_exiting variable \/

return NULL;

}

Exercice 2: Gestion dun Compte Bancaire

Note: Cet exercice doit tre rendu avec un snapshot dex cution.

Dans cet exercice vous allez simuler les d p ts (deposit) et les retraits (withdrawal) effectu s sur un compte bancaire fictif. Dans ce cas, les d p ts et les retraits seront effectu s par des threads synchronis s. La synchronisation est n cessaire pour deux raisons: (1) l'exclusion mutuelle (mises jour ne peuvent pas tre perdues) et (2) parce que le retrait ne peut pas se produire si le montant de retrait demand est sup rieur au solde actuel du compte. Cela signifie que l'acc s au compte (l'objet partag ) doit tre synchronis . Cette application n cessite la coop ration et la communication entre les diff rents threads (threads coop ratifs synchronis s). (En d'autres mots, ce probl me est similaire au probl me du producteur / consommateur o il y a plus qu'un, c dire plusieurs producteurs et plusieurs consommateurs actifs en m me temps. Si un thread de retrait tente de retirer un montant sup rieur au solde actuel, alors il doit bloquer et attendre jusqu' ce qu'un d p t a eu lieu avant de pouvoir essayer nouveau. Comme nous l'avons trait dans les notes de cours, il faudra que les threads de d p t signalent tous les threads de retrait d'attente chaque fois qu'un d p t est achev .

1- Pour garder les choses relativement simples aussi bien que pour voir des r sultats imm diats d'une s rie de transactions (d p ts et retraits), on suppose que les d p ts sont effectu s dans des quantit s allant de 1 $ 200 $ et les retraits sont effectu s dans des quantit s allant de 1 $ 50 $.

2- Vous devriez avoir trois threads de d p t et quatre threads de retrait d'ex cution simultan ment.

3- Une fois qu'un thread de d p t a ex cut , le mettre en veille pendant une milliseconde environ (d pend un peu de la vitesse de votre syst me pour combien de temps vous aurez envie de dormir les discussions des d posants - fondamentalement, nous voulons nous assurer beaucoup plus de retraits que d p ts) pour permettre d'autres threads dex cuter. C'est la seule situation dans laquelle un thread de d p t bloque.

4- Une fois un thread de retrait a ex cut , il c dera un autre thread (ne pas le mettre en veille quand m me). Cela permettra d' viter quun seul thread de retrait occupe le CPU pour longtemps et ex cuter une longue s quence dop rations de retrait. Les threads de retrait bloquent s'ils tentent de retirer plus que le solde actuel du compte.

5- On suppose que tous les threads ont la m me priorit .

6- Utilisez les m canismes de synchronisation ad quats pour g rer le blocage, la signalisation, etc.

7- La sortie de votre programme doit ressembler la figure suivante.

![](data:image/png;base64...)

/\FIN\/

Draft de la solution

1- Ecrire un programme main() o vous d clarez une variable globale partag e int solde=0 ; , un verrou mutex m , et une variable conditionnelle depot , vous cr ez les 3 threads d positeurs (associ s la fonction deposit()) et les quatre threads retraits (associ s la fonction withdraw()) et les attendez avec pthread\_join pour chaque thread.

2- Ci-dessous, une impl mentation de ces fonctions

void \deposit( void \threadid) {

int dep ;

long tid;

tid = (long) threadid;

while (1){

Publicité

dep = rand()%(200-1)+1;

pthread\_mutex\_lock(&m);

compte+=dep;

printf(thread %d deposits %ld \n, tid, dep);

pthread\_mutex\_unlock(&m);

pthread\_cond\_signal(&depot);

sleep (5);

}

}

void \withdraw( void \threadid) {

long tid;

tid = (long) threadid;

int ret ;

while (1){

ret = rand()%(50-1)+1;

pthread\_mutex\_lock(&m);

while(ret > compte){

printf((thread %ld Blocked Insufficient Funds \n, tid);

pthread\_cond\_wait(&depot,&m) ;

}

compte = compte - ret;

printf(thread %d withdraws %ld \n, tid, ret);

pthread\_mutex\_unlock(&m);

}

}

TP 2 - Synchronisation de Threads

Systèmes d’exploitation & Programmation Concurrente · lab

Browse all programmation documents

Ecole Nationale des Sciences de lInformatique A. U. : 2014/2015

Syst mes dexploitation & Programmation Concurrente II2

TP 2 - Synchronisation de Threads

=======================================================

Exercice 1:

Un enseignant dinfo a pr vu faire un rattrapage pour ses groupes dans une salle de TP. Lunique salle de TP disponible peut contenir uniquement 10 tudiants. Cependant le nombre total des tudiants de ces groupes est gal 80. Pour cette raison, lenseignant sest trouv oblig de donner cette s ance de rattrapage plusieurs fois. Pour ce faire, il a utilis lalgorithme suivant : Lenseignant ouvre la porte, attend jusqu ce que la salle devienne pleine, ferme la porte, donne la s ance de rattrapage et ouvre la porte pour laisser sortir les tudiants. Par la suite, il r p te ce m me processus maintes fois jusqu ce que tous les tudiants aient assist la s ance de rattrapage. Evidemment, entre temps, certains tudiants doivent attendre leur tour pour acc der la salle de TP.

Nous allons mod liser ce sc nario avec un programme multithread . On suppose quil existe un thread enseignant et 80 threads tudiants. Ci-dessous, vous trouvez le thread enseignant impl ment en entier, et une partie du thread tudiant. Votre t che consiste terminer limpl mentation du thread tudiant.

Note : Pour terminer limpl mentation de ce thread, vous ne devez pas d clarer dautres variables. Par contre, vous pouvez ne pas utiliser toutes les variables d clar es dans le code ci-dessous. Nous supposons que les fonctions ouvrir\_porte(), fermer\_porte(), et enseigner() sont d finies et impl ment es quelque part ailleurs.

/\ Code \/

#define ETUDIANTS 80

#define CLASS 10

/\ D clarations ne pas modifier \/

int etudiants\_entrant = 0; /\ etudiants entrant la salle\/

int etudiants\_sortant = 0; /\ etudiants quittant la salle\/

sem\_t mutex1;

sem\_t mutex2;

sem\_t mutex3;

sem\_t entrer\_file;

sem\_t sortir\_file;

sem\_t tous\_entres;

sem\_t tous\_sortis;

/\ Ne rien modifier ici \/

int main()

{

pthread\_t tid, student\_tid ;

int i;

/\ initialize our semaphores \/

Advertisement

sem\_init(&mutex1, 0, 0);

sem\_init(&mutex2, 0, 1);

sem\_init(&mutex3, 0, 1);

sem\_init(&entrer\_file, 0, 0);

sem\_init(&sortir\_file, 0, 0);

sem\_init(&tous\_entres, 0, 0);

sem\_init(&tous\_sortis, 0, 0);

pthread\_create(&tid, NULL, thread\_enseignant, NULL);

for (i = 0; i < ETUDIANTS; i++) {

pthread\_create(&student\_tid , NULL, thread\_etudiant, (void \*)i);

}

for (i = 0; i < ETUDIANTS; i++) {

pthread\_join(student\_tid , NULL);

}

printf("Cest tout.\n");

exit(0);

}

/\ thread\_enseignant ne rien modifier ici \/

void \thread\_enseignant(void \arg)

{

int i;

ouvrir\_porte();

while (1) {

for (i = 0; i < CLASS; i++) {

V(&entrer\_file);

}

P(&tous\_entres);

Advertisement

Fermer\_porte();

enseigner();

ouvrir\_porte();

for (i = 0; i < CLASS; i++) {

V(&sortir\_file);

}

P(&tous\_sortis);

}

}

Question:

Compl tez le code pour la fonction thread\_etudiant() qui suit. Vous ne devez pas ajouter dautres variables mais vous pouvez ne pas utiliser certaines variables d clar es.

Note: Vous devez uniquement ajouter quelques lignes de code ici sans pour autant changer la structure de base de cette fonction.

R ponse:

void \thread\_etudiant(void \arg){

P(&entrer\_file); /\ Attendre une place \/

/\ entrer dans la salle \/

P(&mutex2); /\ Mutex pour students\_entering variable \/

etudiants\_entrant += 1;

if (etudiants\_entrant == CLASS) {

V(&tous\_entres); /\ last one in signals it's time to start class \/

etudiants\_entrant = 0;

}

V(&mutex2); /\ release lock for students\_entering variable \/

P(&sortir\_file); /\ wait to be told to leave \/

/\ Quitter la salle \/

P(&mutex3);/\ acquire lock for students\_exiting variable \/

etudiants\_sortant += 1;

Advertisement

if (etudiants\_sortant == CLASS) {

V(&tous\_sortis); /\ last one out signals to let the next batch in \/

etudiants\_sortant = 0;

}

V(&mutex3); /\ release lock for students\_exiting variable \/

return NULL;

}

Exercice 2: Gestion dun Compte Bancaire

Note: Cet exercice doit tre rendu avec un snapshot dex cution.

Dans cet exercice vous allez simuler les d p ts (deposit) et les retraits (withdrawal) effectu s sur un compte bancaire fictif. Dans ce cas, les d p ts et les retraits seront effectu s par des threads synchronis s. La synchronisation est n cessaire pour deux raisons: (1) l'exclusion mutuelle (mises jour ne peuvent pas tre perdues) et (2) parce que le retrait ne peut pas se produire si le montant de retrait demand est sup rieur au solde actuel du compte. Cela signifie que l'acc s au compte (l'objet partag ) doit tre synchronis . Cette application n cessite la coop ration et la communication entre les diff rents threads (threads coop ratifs synchronis s). (En d'autres mots, ce probl me est similaire au probl me du producteur / consommateur o il y a plus qu'un, c dire plusieurs producteurs et plusieurs consommateurs actifs en m me temps. Si un thread de retrait tente de retirer un montant sup rieur au solde actuel, alors il doit bloquer et attendre jusqu' ce qu'un d p t a eu lieu avant de pouvoir essayer nouveau. Comme nous l'avons trait dans les notes de cours, il faudra que les threads de d p t signalent tous les threads de retrait d'attente chaque fois qu'un d p t est achev .

1- Pour garder les choses relativement simples aussi bien que pour voir des r sultats imm diats d'une s rie de transactions (d p ts et retraits), on suppose que les d p ts sont effectu s dans des quantit s allant de 1 $ 200 $ et les retraits sont effectu s dans des quantit s allant de 1 $ 50 $.

2- Vous devriez avoir trois threads de d p t et quatre threads de retrait d'ex cution simultan ment.

3- Une fois qu'un thread de d p t a ex cut , le mettre en veille pendant une milliseconde environ (d pend un peu de la vitesse de votre syst me pour combien de temps vous aurez envie de dormir les discussions des d posants - fondamentalement, nous voulons nous assurer beaucoup plus de retraits que d p ts) pour permettre d'autres threads dex cuter. C'est la seule situation dans laquelle un thread de d p t bloque.

4- Une fois un thread de retrait a ex cut , il c dera un autre thread (ne pas le mettre en veille quand m me). Cela permettra d' viter quun seul thread de retrait occupe le CPU pour longtemps et ex cuter une longue s quence dop rations de retrait. Les threads de retrait bloquent s'ils tentent de retirer plus que le solde actuel du compte.

5- On suppose que tous les threads ont la m me priorit .

6- Utilisez les m canismes de synchronisation ad quats pour g rer le blocage, la signalisation, etc.

7- La sortie de votre programme doit ressembler la figure suivante.

![](data:image/png;base64...)

/\FIN\/

Draft de la solution

1- Ecrire un programme main() o vous d clarez une variable globale partag e int solde=0 ; , un verrou mutex m , et une variable conditionnelle depot , vous cr ez les 3 threads d positeurs (associ s la fonction deposit()) et les quatre threads retraits (associ s la fonction withdraw()) et les attendez avec pthread\_join pour chaque thread.

2- Ci-dessous, une impl mentation de ces fonctions

void \deposit( void \threadid) {

int dep ;

long tid;

tid = (long) threadid;

while (1){

Advertisement

dep = rand()%(200-1)+1;

pthread\_mutex\_lock(&m);

compte+=dep;

printf(thread %d deposits %ld \n, tid, dep);

pthread\_mutex\_unlock(&m);

pthread\_cond\_signal(&depot);

sleep (5);

}

}

void \withdraw( void \threadid) {

long tid;

tid = (long) threadid;

int ret ;

while (1){

ret = rand()%(50-1)+1;

pthread\_mutex\_lock(&m);

while(ret > compte){

printf((thread %ld Blocked Insufficient Funds \n, tid);

pthread\_cond\_wait(&depot,&m) ;

}

compte = compte - ret;

printf(thread %d withdraws %ld \n, tid, ret);

pthread\_mutex\_unlock(&m);

}

}