5. Terminaison, jointure et ordre d’exécution

Un événement retient d’abord le travail. Après sa libération et join, le thread a terminé et la valeur produite est disponible.
- Avant la libération, le thread est vivant et la liste de résultats est vide.
- join attend la terminaison du thread ciblé; cet exemple utilise l’API Python, distincte de pthread_join.
Lire la capture en texte
thread.start()
libération du travail ; thread.join()
Avant libération : thread vivant = True ; résultat = []
Après join() : thread vivant = False ; résultat = [42]Démonstration Station Minuit · Ubuntu 24.04 / WSL2 · Python 3 · 15 octobre 2026 (Toronto). Sortie réelle remise en page et capturée; exemple ajouté, distinct du matériel officiel.
5.1 pthread_join
Code (c) · sélectionner pour copier
int pthread_join(pthread_t tid, void **status);
pthread_join bloque le thread appelant jusqu’à la terminaison du thread tid. status peut recevoir la valeur finale; NULL indique qu’elle n’est pas requise. Le tutoriel LLNL rappelle qu’un thread joignable ne doit être joint qu’une fois. Un thread détaché libère automatiquement ses ressources de terminaison, mais ne peut pas être joint.
join exprime une relation logique : « poursuivre après la fin de ce thread ». sleep exprime seulement une attente temporelle. Une pause d’une seconde ne prouve pas que le travail est fini; la charge et l’ordonnancement peuvent toujours modifier la durée réelle.
Le créateur qui poursuit sans attendre produit une relation asynchrone. Lorsqu’il joint un travailleur avant de dépendre de son résultat, la relation devient synchrone sur cette terminaison.
5.2 Préserver ou détruire la concurrence
Patron concurrent :
- créer tous les travailleurs;
- les laisser progresser;
- joindre ensuite chacun d’eux.
Patron sérialisé :
- créer un travailleur;
- le joindre immédiatement;
- seulement ensuite créer le suivant.
Le deuxième patron peut être voulu lorsqu’une dépendance séquentielle existe, mais il annule le parallélisme si les travailleurs étaient censés avancer ensemble.
5.3 Lire une trace correctement
Il faut distinguer quatre ordres :
- l’ordre dans lequel le programme appelle
pthread_create; - l’ordre de démarrage réel des travailleurs;
- l’ordre des opérations observables comme les affichages;
- les relations de précédence garanties par les
joinou d’autres primitives.
Une trace obtenue une fois n’est pas une spécification. L’ordonnanceur peut choisir un ordre différent à l’exécution suivante.
Dans l’exemple A/B/C, A et B sont créés ensemble et leurs affichages peuvent s’entrelacer. Le thread principal joint A et B avant de créer C. La garantie est donc uniquement : C commence après la fin de A et de B. Aucun ordre relatif complet n’est imposé entre A et B.