Un processus est une instance d'un programme en cours d'exécution. Chaque processus possède son propre espace mémoire et peut contenir plusieurs threads (ou fils d'exécution), qui partagent cet espace mémoire mais s'exécutent indépendamment.
L'exécution des threads est non déterministe : l'ordonnancement du processeur varie selon la charge du système, ce qui entraîne des résultats imprévisibles si des threads accèdent simultanément aux mêmes ressources sans synchronisation.
Programmation avec les Threads
Bibliothèque pthread en C
pthread est une bibliothèque standard pour gérer les threads en C.
Voici les principales directives et instructions de pthread :
- include <pthread.h> : inclus la bibliothèque ;
- pthread_create() : crée un thread ;
- pthread_join() : attend la fin du thread ;
- pthread_exit() : termine un thread proprement.
Bibliothèque Thread d'OCaml
OCaml supporte les threads via le module Thread.
Voici les principales fonctions de Thread :
- Thread.create f arg : crée un thread exécutant f arg ;
- Thread.join t : attend la fin du thread t ;
- Thread.exit () : termine un thread.
Interblocage
Un interblocage (ou deadlock) est une situation où plusieurs threads se bloquent indéfiniment en attendant une ressource détenue par un autre thread. Aucun ne peut avancer, créant un blocage total du système.
Solutions possibles pour éviter les situations d'interblocage :
- Ordonnancement strict : forcer un ordre de prise des ressources ;
- Timeouts : forcer un thread à relâcher une ressource après un certain temps ;
- Hiérarchie de verrouillage : imposer un ordre dans l'acquisition des ressources.
Modèle de synchronisation
La synchronisation des threads est essentielle pour garantir un accès contrôlé aux ressources partagées, et éviter l'interblocage. Plusieurs modèles classiques permettent d'organiser l'exécution des threads et d'éviter les conflits.
Rendez-vous
Le rendez-vous est un mécanisme où deux threads doivent attendre l'un l'autre avant de poursuivre leur exécution. Il est utilisé lorsqu'un thread ne peut avancer qu'après avoir échangé des informations avec un autre. On le retrouve dans le modèle client-serveur notamment.
Producteur-Consommateur
Ce modèle synchronise deux types de threads :
- Les producteurs génèrent des données et les placent dans un tampon partagé.
- Les consommateurs récupèrent ces données et les traitent.
Un problème clé est d'éviter les conditions de course (accès concurrent au tampon) et la surcharge (le producteur ne doit pas remplir un tampon déjà plein).