Thread POSIX
Ce laboratoire présente la programmation des threads POSIX en langage C. Il permet d'apprendre à créer des threads, à gérer leur exécution concurrente, puis à synchroniser leur ordre d'exécution à l'aide de sémaphores.
D'après le document Thread POSIX
Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

Document source
Programming · PDF · 3 pages
Afficher l'aperçu du document
Ce laboratoire présente la programmation des threads POSIX en langage C. Il permet d'apprendre à créer des threads, à gérer leur exécution concurrente, puis à synchroniser leur ordre d'exécution à l'aide de sémaphores. Pour réaliser ce TP, un environnement de développement C avec support POSIX (Linux, macOS, ou autre système compatible) est nécessaire, ainsi que la connaissance des bases du langage C et des threads.
Objectifs
- Créer et lancer des threads POSIX en C.
- Comprendre le comportement concurrent des threads.
- Utiliser pthread_create, pthread_exit et pthread_join.
- Synchroniser l'exécution des threads avec des sémaphores POSIX.
- Contrôler l'ordre d'affichage des threads sans utiliser sleep pour la synchronisation.
Prérequis et installation
- Un compilateur C compatible POSIX (gcc recommandé).
- Bibliothèques pthread et semaphore disponibles (généralement incluses dans les distributions Linux).
- Connaissances de base en programmation C et notions sur les threads.
- Commande de compilation avec l'option
-pthreadpour lier la bibliothèque pthread.
Création de threads
Dans ce premier exercice, vous devez programmer et compiler un exemple simple de création de thread vu en cours. Il faut veiller à utiliser les options de compilation correctes, notamment -pthread.
Exécutez ce programme et observez son comportement. Vous devriez voir que les threads s'exécutent concurremment, affichant leurs messages indépendamment.
Exercice 2 : Lancement de plusieurs threads exécutant la même fonction
Voici la fonction que chaque thread doit exécuter :
void *ma_nouvelle_sequence_control (void * arg)
{
int i;
for (i = 0 ; i < 10 ; i++) {
printf ("Thread %s: %d\n", (char*)arg, i);
sleep (1);
}
pthread_exit (0);
}
Réalisez un programme C qui lance 3 threads exécutant cette fonction, chacun recevant un nom différent en argument. Utilisez les fonctions pthread_create, pthread_exit et pthread_join.
Exécutez votre programme et observez que les trois threads s'exécutent simultanément, affichant leurs messages en alternance selon la planification du système.
Introduction à la synchronisation des threads
Exemple sans synchronisation
Voici un programme simple qui crée deux threads :
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *thread1_process (void * arg)
{
sleep (1);
printf ("[2]\n");
pthread_exit (0);
}
void *thread2_process (void * arg)
{
sleep (5);
printf ("[1]\n");
pthread_exit (0);
}
int main (int argc, char **argv)
{
pthread_t th1, th2;
void *ret;
if (pthread_create (&th1, NULL, thread1_process, NULL) < 0)
{
fprintf (stderr, "pthread_create error\n");
exit (1);
}
if (pthread_create (&th2, NULL, thread2_process, NULL) < 0) {
fprintf (stderr, "pthread_create error\n");
exit (1);
}
(void)pthread_join (th1, &ret);
(void)pthread_join (th2, &ret);
return 0;
}
Exécutez ce programme. Vous constaterez que l'affichage est :
[2]
[1]
car le thread1 affiche après 1 seconde et le thread2 après 5 secondes.
Contrôler l'ordre d'exécution avec un sémaphore
Pour forcer un ordre d'exécution, on utilise un sémaphore POSIX :
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
static sem_t my_sem;
void *thread1_process (void * arg)
{
sleep (1);
sem_wait (&my_sem);
printf ("[2]\n");
pthread_exit (0);
}
void *thread2_process (void * arg)
{
sleep (5);
printf ("[1]\n");
sem_post (&my_sem);
pthread_exit (0);
}
int main (int ac, char **av)
{
pthread_t th1, th2;
void *ret;
sem_init (&my_sem, 0, 0);
if (pthread_create (&th1, NULL, thread1_process, NULL) < 0) {
fprintf (stderr, "pthread_create error\n");
exit (1);
}
if (pthread_create (&th2, NULL, thread2_process, NULL) < 0) {
fprintf (stderr, "pthread_create error\n");
exit (1);
}
(void)pthread_join (th1, &ret);
(void)pthread_join (th2, &ret);
}
Exécutez cette version. L'affichage sera :
[1]
[2]
car le thread2 libère le sémaphore avec sem_post après son affichage, permettant au thread1 d'afficher ensuite.
La variable my_sem sert donc de barrière de synchronisation, contrôlant l'ordre d'exécution des threads.
Cas pratique : affichage ordonné de plusieurs threads
Réalisez un programme qui lance 10 threads numérotés de 0 à 9. Chaque thread doit afficher son numéro.
- L'ordre de création des threads est croissant (de 0 à 9).
- L'affichage doit se faire dans l'ordre décroissant (de 9 à 0).
- Il ne faut pas utiliser
sleep()pour la synchronisation temporelle.
Pour cela, vous pouvez utiliser des sémaphores ou une autre méthode de synchronisation pour forcer l'ordre d'affichage inverse à celui de création.
Résultats attendus
- Dans l'exercice de création simple, les threads affichent leurs messages en parallèle, sans ordre garanti.
- Dans l'exemple avec sémaphore, l'ordre d'affichage est contrôlé et correspond à la séquence attendue.
- Dans le cas pratique, les numéros des threads doivent s'afficher dans l'ordre décroissant de 9 à 0, malgré une création dans l'ordre croissant.
Pièges courants
- Oublier d'utiliser l'option
-pthreadlors de la compilation, ce qui provoque des erreurs de linkage. - Ne pas utiliser
pthread_joinpour attendre la fin des threads, ce qui peut entraîner la fin prématurée du programme principal. - Utiliser
sleep()pour synchroniser l'ordre d'exécution, ce qui est non fiable et dépendant du système. - Ne pas initialiser correctement le sémaphore avec
sem_init. - Ne pas appeler
sem_postdans le thread qui doit libérer la barrière, bloquant ainsi les autres threads.
Commentaires
Aucun commentaire pour le moment. Posez la première question.