Université de Carthage Département
Faculté des Sciences de Bizerte d’informatique
-------------------------------------------------------------------------------------------------------------------------------------
Niveau : GLSI 1 A.U. : 2022/2023
Responsable : R. Beltaifa Module : Sys. d’exp. 2
TP4 : Les threads
- Un thread (ou fil d’exécution ou processus léger) est une partie du code d’un
programme (une fonction ou une méthode), qui se déroule parallèlement à
d’autre parties du programme.
- Un processus est un programme qui s'exécute selon un chemin unique avec un
seul compteur ordinal. On dit qu'il a un flot de contrôle unique ou un seul
thread.
- Multithread : associer à un même processus plusieurs fils d'exécution
- Chaque thread a son propre numéro (thread identifier Tid)
Code source C manipulant des threads:
Un programme C utilisant la bibliothèque libpthread.a doit disposer de l'entête
suivante : #include <pthread.h>
Compilation et édition des liens :
$ gcc -o progthread progthread.c –lpthread
Ou
$ gcc –lpthread progthread.c –o progthread
Fonctions de manipulation des threads (~60 fonctions) de la
bibliothèque libpthread.a dans un programme C :
Création de threads : pthread_create()
Attendre la fin d’un thread : pthread_join()
Les fonctions étudiées pendant les séances de cours sont décrites ci-dessous :
1. Fonction de Création d’un thread : pthread_create
Pour créer un thread, il faut créer une fonction qui va s’exécuter dans le thread, qui a
pour prototype : void * fonction ( void * arg ). Dans cette fonction, on met le code
qui doit être exécuté dans le thread. On crée ensuite le thread par un appel à la fonction
Université de Carthage Département
Faculté des Sciences de Bizerte d’informatique
-------------------------------------------------------------------------------------------------------------------------------------
pthread_create, et on lui passe en argument la fonction fonction dans un pointeur de fonction
(et son argument arg).
int pthread_create ( pthread_t * thread , pthread_attr_t * attributs , void
(* fonction ) ( void * arg ) , void * arg ) ;
int : renvoie 0 si le thread a été créé avec succès et un nombre négatif sinon
1er arg : passage par adresse de l’identifiant du thread (de type pthread_t).
2ème arg: attributs du thread permettant de spécifier la taille de la pile, la priorité, la
politique de planification, etc.. On peut mettre NULL pour avoir les attributs par
défaut
3ème arg : est un pointeur sur la fonction à exécuter dans le thread
4ème arg : l’argument de la fonction de thread.
2. Attente la fin d’exécution d’un thread : Pthread_join
Lorsqu'un processus lourd crée une tâche, s'il ne lui est pas explicitement indiqué
d'attendre la fin d'exécution de cette tâche, alors à sa terminaison elle forcera l'arrêt de
la tâche créée. Pour éviter cela, on utilise la fonction pthread_join .
Le prototype de la fonction pthread_join est :
int pthread_join(pthread_t thread, void** thread_return)
• Suspend l'exécution du thread appelant jusqu'à la terminaison du thread indiqué
en premier argument.
• Le pointeur passé en seconde position est la valeur de retour du thread fini.
3. Identifiant du thread : Pthread_self
Pour connaître son propre identifiant, un thread invoque la fonction pthread_self( ),
qui lui renvoie une valeur de type pthread_t :
pthread_t pthread_self (void);
4. Terminaison de threads : Pthread_exit
pthread_exit() permet à un processus léger de terminer son exécution, en retournant
l'état de terminaison.
void pthread_exit(void *valeur_de_retour);
L’exemple suivant implémente les fonctions de threads présentées ci-dessus :
Université de Carthage Département
Faculté des Sciences de Bizerte d’informatique
-------------------------------------------------------------------------------------------------------------------------------------
Université de Carthage Département
Faculté des Sciences de Bizerte d’informatique
-------------------------------------------------------------------------------------------------------------------------------------
Exercices :
Exercice 1 :
On veut qu’un processus lourd remplie un tableau d’entiers de taille N par des entiers ordonnés
(0,1, …N) et lance 3 processus légers :
le premier affiche le contenu du tableau
le second place des 1 dans chaque cellule de ce tableau ;
le troisième place des 2 dans chaque cellule de ce tableau.
Commentez les résultats d’exécution obtenues.
Correction (ex1TP4.c)
#include<stdio.h>
#include<pthread.h>
int N;
void *affichage(void *arg)
{
int *t=(int *)arg;
printf("premier thread %ld\n",pthread_self());
for (int i=0;i<N;i++)
printf("tab[%d]=%d\n",i,*(t+i));
pthread_exit(NULL);
}
void *un(void *arg)
{
int *t=(int *)arg;
printf("second thread %ld\n",pthread_self());
for (int i=0;i<N;i++)
*(t+i)=1;
pthread_exit(NULL);
}
void *deux(void *arg)
{
int *t=(int *)arg;
printf("Troisième thread %ld\n",pthread_self());
for (int i=0;i<N;i++)
*(t+i)=2;
pthread_exit(NULL);
}
Université de Carthage Département
Faculté des Sciences de Bizerte d’informatique
-------------------------------------------------------------------------------------------------------------------------------------
int main()
{
pthread_t th1,th2,th3;
int *tab;
printf("donner la taille du tableau\n");
scanf("%d", &N);;
for (int i=0;i<N;i++)
*(tab+i)=i;
pthread_create(&th1,NULL,affichage,tab);
pthread_join(th1,NULL);
pthread_create(&th2,NULL,un,tab);
pthread_create(&th3,NULL,deux,tab);
pthread_join(th2,NULL);
pthread_join(th3,NULL);
printf("Thread principal %ld\n",pthread_self());
for (int i=0;i<N;i++)
printf("tabf[%d]=%d\n",i,*(tab+i));
//pthread_join(th3,NULL);
}
Exercice 2 :
Ecrire un programme C ayant le comportement suivant :
Université de Carthage Département
Faculté des Sciences de Bizerte d’informatique
-------------------------------------------------------------------------------------------------------------------------------------
- des threads sont créés (leur nombre étant passé en paramètre lors du lancement
du programme(utilisez argc et argv) ;
- chaque thread affiche le message « hello » et son numéro ;
- le processus principal attend la terminaison des différents threads créés.
Correction :
(ex2TP4.c)
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
void *affichage(void *arg)
{
printf("Hello, je suis le thread de tid = %ld\n",pthread_self());
pthread_exit(NULL);
}
int main(int argc, char* argv[])
{
pthread_t *threads;
int n=atoi(argv[1]);
threads = malloc(sizeof(pthread_t) *n);
for(int i=0;i<n;i++)
pthread_create(&threads[i],NULL,affichage,NULL);
for(int i=0;i<n;i++)
pthread_join(threads[i],NULL);
printf("Thread principal, tid= %ld\n",pthread_self());
}