0% ont trouvé ce document utile (0 vote)
31 vues7 pages

Correction TP4 Thread

Le document traite de l'utilisation des threads en programmation, en mettant l'accent sur les avantages des processus légers et les défis liés au partage des ressources. Il présente des exercices pratiques sur la création de threads, la synchronisation avec des mutex et des sémaphores, ainsi que des modifications de code pour garantir un affichage déterministe. Enfin, il aborde l'importance de la gestion des ressources partagées et propose des solutions pour équilibrer l'exécution des threads.

Transféré par

ines333bouderbela
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
31 vues7 pages

Correction TP4 Thread

Le document traite de l'utilisation des threads en programmation, en mettant l'accent sur les avantages des processus légers et les défis liés au partage des ressources. Il présente des exercices pratiques sur la création de threads, la synchronisation avec des mutex et des sémaphores, ainsi que des modifications de code pour garantir un affichage déterministe. Enfin, il aborde l'importance de la gestion des ressources partagées et propose des solutions pour équilibrer l'exécution des threads.

Transféré par

ines333bouderbela
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

ENICarthage 2ème Année Ingénieur Informatique

Correction TP N°4

Les Threads

Les Threads :

Le gros avantage lié à la notion de processus léger (thread) est un allégement des opérations de
commutations de contexte (le contexte mémoire est le même). De même, l’opération de création
d’un nouveau fil d’exécution est sensiblement allégée puisqu’elle ne nécessite plus la duplication
complète de l’espace d’adressage du processus père.
Or comme les processus légers au sein d’un même processus partagent le même espace
d’adressage, il s’ensuit des problèmes de partage des ressources importants qu’on peut gèrer
avec les mutex et les sémaphores.
Exercice 1 :
Soit le programme suivant :
#include <stdio.h>
#include <pthread.h>
void *task1 (void *arg )
{ printf (" Thread 1 \n" );
pthread_exit (0);
return NULL;
}
void *task2 (void *arg )
{ printf (" Thread 2 \n");
pthread_exit (0);
return NULL;
}
int main ( )
{
pthread_t t1, t2;
printf ("main Init\n");
pthread_create (&t1, NULL, task1, NULL);
pthread_create (&t2, NULL, task2, NULL);
printf ("main Fin\n");
return 0;
}
1. Tester ce programme, l'ordre d'affichage est-il déterministe ?
NB : Pour exécuter, il faut ajouter -lpthread ou -pthread (gcc ex1.c -o ex1 -lpthread).
Lors de l’exécution, l’ordre d’affichage n’est pas déterministe et cela dépend de l’ordre
d’exécution des threads.
2. Modifier ce programme pour avoir toujours l'affichage suivant :
main Init
thread1

1
ENICarthage 2ème Année Ingénieur Informatique

thread2
main Fin
il faut ajouter avant printf(“main Fin\n”):
pthread_join(t1,&status);
pthread_join(t2,&status);
avec dans la declaration : void * status;
Cela va permettre au processus père d'attendre la fin du thread 1 et du thread 2 c'est à dire
la fin de l'exécution des fonctions exécutées par ceux-ci.
2. Modifier le dernier programme et utiliser une seule fonction task au lieu de task1 et task2.
L'output doit être le même que celui de la question 2.
On va utiliser ici une fonction (task) paramétrée :
#include <stdio.h>
#include <pthread.h>
void *task (void *arg )
{ printf (" Thread %d \n",(int)arg );
pthread_exit (0);
return NULL;
}
int main ( )
{
pthread_t t1, t2;
int i=1 ;
int j=2 ;
void * status ;
printf ("main Init\n");
pthread_create (&t1, NULL, task,(void*)i);
pthread_create (&t2, NULL, task,(void*)j);
printf ("main Fin\n");
return 0;
}

Exercice 2 :
Soit le programme suivant :
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
/*1*/
int data=0;
void *fonctionplus (void *arg)
{ int i ;
for (i=0;i<4;++i)
{
/*2*/
data++;

2
ENICarthage 2ème Année Ingénieur Informatique

printf("Thread plus %d\n", data);


/*3*/
}
pthread_exit(0);
return NULL;
}
void *fonctionmoins (void *arg)
{ int i;
for(i=0;i<4;++i)
{
/*4*/
data--;
printf("Thread moins %d\n", data);
/*5*/
}
pthread_exit(0);
return NULL;
}
int main (void)
{ pthread_t tid1, tid2 ;
void *status ;
int i ;
printf("main Init\n");
/*6*/
pthread_create(&tid1,NULL,fonctionplus,NULL) ;
pthread_create(&tid2,NULL,fonctionmoins,NULL);
for (i=0;i<4;++i)
{
/*7*/
printf ("\n Variable partage = %d\n",data) ;
/*8*/
}
printf ("main Fin \n") ;
pthread_join(tid1,&status) ;
pthread_join(tid2,&status);
/*9*/
return 0 ;
}
1. Tester ce programme
On remarque que les deux threads ont une variable partagée (data). Pour cela, il faut les
délimiter par soit les mutex soit les sémaphores.
2. Terminer les passages manquants marqués par les numéros en utilisant les mutex.
#include <pthread.h>
#include <unistd.h>

3
ENICarthage 2ème Année Ingénieur Informatique

#include <stdio.h>
pthread_mutex_t S;
int data=0;
void *fonctionplus (void *arg)
{ int i ;
for (i=0;i<4;++i)
{
pthread_mutex_lock(&S);
data++;
printf("Thread plus %d\n", data);
pthread_mutex_unlock(&S);
}
pthread_exit(0);
return NULL;
}
void *fonctionmoins (void *arg)
{ int i;
for(i=0;i<4;++i)
{
pthread_mutex_lock(&S);
data--;
printf("Thread moins %d\n", data);
pthread_mutex_unlock(&S);
}
pthread_exit(0);
return NULL;
}
int main (void)
{ pthread_t tid1, tid2 ;
void *status ;
int i ;
printf("main Init\n");
/*6*/
pthread_create(&tid1,NULL,fonctionplus,NULL) ;
pthread_create(&tid2,NULL,fonctionmoins,NULL);
for (i=0;i<4;++i)
{
pthread_mutex_lock(&S);
printf ("\n Variable partage = %d\n",data) ;
pthread_mutex_unlock(&S);
}
printf ("main Fin \n") ;
pthread_join(tid1,&status) ;
pthread_join(tid2,&status);

4
ENICarthage 2ème Année Ingénieur Informatique

pthread_mutex_destroy(&S);
return 0 ;
}
2. Balancer l'exécution entre le thread principal, le thread d'incrémentation et le thread de
décrémentation en utilisant sleep.
Ici on part du principe que pour alterner entre l’exécution du thread principal, le thread
d'incrémentation et le thread de décrémentation, il faut que tous les threads attendent la
même période.
Aussi, nous notons que le timing est étroitement lié au processeurs.
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
pthread_mutex_t S;
int data=0;
void *fonctionplus (void *arg)
{ int i ;
for (i=0;i<4;++i)
{
sleep(1);
pthread_mutex_lock(&S);
data++;
printf("Thread plus %d\n", data);
pthread_mutex_unlock(&S);
sleep(2);
}
pthread_exit(0);
return NULL;
}
void *fonctionmoins (void *arg)
{ int i;
for(i=0;i<4;++i)
{
sleep(1);
pthread_mutex_lock(&S);
data--;
printf("Thread moins %d\n", data);
pthread_mutex_unlock(&S);
sleep(2);
}
pthread_exit(0);
return NULL;
}
int main (void)
{ pthread_t tid1, tid2 ;

5
ENICarthage 2ème Année Ingénieur Informatique

void *status ;
int i ;
printf("main Init\n");
pthread_mutex_init(&S,NULL);
pthread_create(&tid1,NULL,fonctionplus,NULL) ;
pthread_create(&tid2,NULL,fonctionmoins,NULL);
for (i=0;i<4;++i)
{
pthread_mutex_lock(&S);
printf ("\n Variable partage = %d\n",data) ;
pthread_mutex_unlock(&S);
sleep(3);
}
printf ("main Fin \n") ;
pthread_join(tid1,&status) ;
pthread_join(tid2,&status);
pthread_mutex_destroy(&S);
return 0 ;
}
3. Reprendre le code précédent en utilisant les sémaphores.
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <semaphore.h>
sem_t S;
int data=0;
void *fonctionplus (void *arg)
{ int i ;
for (i=0;i<4;++i)
{
sleep(1);
sem_wait(&S);
data++;
printf("Thread plus %d\n", data);
sem_post(&S);
sleep(2);
}
pthread_exit(0);
return NULL;
}
void *fonctionmoins (void *arg)
{ int i;
for(i=0;i<4;++i)
{

6
ENICarthage 2ème Année Ingénieur Informatique

sleep(1);
sem_wait(&S);
data--;
printf("Thread moins %d\n", data);
sem_wait(&S);
sleep(2);
}
pthread_exit(0);
return NULL;
}
int main (void)
{ pthread_t tid1, tid2 ;
void *status ;
int i ;
printf("main Init\n");
sem_init(&S,0,1);
pthread_create(&tid1,NULL,fonctionplus,NULL) ;
pthread_create(&tid2,NULL,fonctionmoins,NULL);
for (i=0;i<4;++i)
{
sem_wait(&S);
printf ("\n Variable partage = %d\n",data) ;
sem_wait(&S);
sleep(3);
}
printf ("main Fin \n") ;
pthread_join(tid1,&status) ;
pthread_join(tid2,&status);
sem_destroy(&S);
return 0 ;
}

Vous aimerez peut-être aussi