Les discussions se présentent sous deux angles: les systèmes d'exploitation et les langages de programmation. Dans les deux cas, les attributs d'un thread varient.
Une définition minimale d'un thread est que ce sont des choses qui se passent en séquence, une chose après l'autre.
Dans un modèle d'exécution de machine typique, chaque thread a son propre ensemble de registres à usage général et son propre compteur de programme. Si la machine définit un registre spécifique en tant que pointeur de pile, il y a une copie par thread.
Du point de vue du système d'exploitation, le minimum qu'un système d'exploitation doit faire pour prendre en charge les threads est de fournir un moyen de basculer entre eux. Cela peut se produire automatiquement ( multitâche prémptif ou uniquement lorsque le thread fait une demande explicite (multitâche coopératif; dans ce cas, les threads sont parfois appelés fibres ). Il existe également des modèles hybrides avec à la fois des rendements de préemption et de coopération, par exemple une préemption entre les threads de différents groupes. ou des tâches mais des rendements explicites entre les threads du même groupe / tâche. La commutation entre les threads implique au minimum la sauvegarde des valeurs de registre de l'ancien thread et la restauration des valeurs de registre du nouveau thread.
Dans un système d'exploitation multitâche qui assure l' isolement entre les tâches (ou processus , vous pouvez traiter ces termes comme des synonymes dans un contexte de système d'exploitation), chaque tâche a ses propres ressources, en particulier l'espace d'adressage, mais aussi des fichiers ouverts, des privilèges, etc. à fournir par le noyau du système d' exploitation , une entité qui est au-dessus des processus. Chaque tâche a normalement au moins un thread - une tâche qui n'exécute pas de code n'est pas très utile. Le système d'exploitation peut ou non prendre en charge plusieurs threads dans la même tâche; par exemple, l'Unix d'origine ne l'a pas fait. Une tâche peut toujours exécuter plusieurs threads en s'arrangeant pour basculer entre eux - cela ne nécessite aucun privilège spécial. C'est ce qu'on appelle les « threads utilisateur», En particulier dans un contexte Unix. De nos jours, la plupart des systèmes Unix fournissent des threads du noyau, en particulier parce que c'est la seule façon d'avoir plusieurs threads du même processus s'exécutant sur différents processeurs.
La plupart des ressources du système d'exploitation en dehors du temps de calcul sont attachées aux tâches, pas aux threads. Certains systèmes d'exploitation (par exemple, Linux) délimitent explicitement les piles, auquel cas chaque thread a le sien; mais il y a des OS où le noyau ne sait rien des piles, ils ne sont qu'une partie du tas en ce qui le concerne. Le noyau gère également généralement un contexte de noyau pour chaque thread, qui est une structure de données contenant des informations sur ce que le thread fait actuellement; cela permet au noyau de gérer simultanément plusieurs threads bloqués dans un appel système.
En ce qui concerne le système d'exploitation, les threads d'une tâche exécutent le même code, mais sont à des positions différentes dans ce code (valeurs de compteur de programme différentes). Il peut ou non arriver que certaines parties du code d'un programme soient toujours exécutées dans des threads spécifiques, mais il existe généralement du code commun (par exemple des fonctions utilitaires) qui peut être appelé à partir de n'importe quel thread. Tous les threads voient les mêmes données, sinon ils seraient considérés comme des tâches différentes; si certaines données ne sont accessibles que par un thread particulier, il s'agit généralement uniquement de la compétence du langage de programmation, et non du système d'exploitation.
Dans la plupart des langages de programmation, le stockage est partagé entre les threads du même programme. Il s'agit d'un modèle de mémoire partagée de programmation simultanée; c'est très populaire, mais aussi très sujet aux erreurs, car le programmeur doit être prudent lorsque les mêmes données sont accessibles par plusieurs threads car des conditions de concurrence peuvent se produire. Notez que même les variables locales peuvent être partagées entre les threads: «variable locale» (généralement) signifie une variable dont le nom n'est valide que pendant une exécution d'une fonction, mais un autre thread peut obtenir un pointeur sur cette variable et y accéder.
Il existe également des langages de programmation où chaque thread a son propre stockage, et la communication entre eux se fait en envoyant des messages sur les canaux de communication. Il s'agit du modèle de transmission de messages de programmation simultanée. Erlangest le principal langage de programmation qui se concentre sur le passage de messages; son environnement d'exécution a une gestion très légère des threads, et il encourage les programmes écrits avec de nombreux threads de courte durée, contrairement à la plupart des autres langages de programmation où la création d'un thread est une opération relativement coûteuse et l'environnement d'exécution ne peut pas prendre en charge un très grand nombre de threads en même temps. Le sous-ensemble séquentiel d'Erlang (la partie du langage qui se produit dans un thread, en particulier la manipulation de données) est (principalement) purement fonctionnel; ainsi un thread peut envoyer un message à un autre thread contenant des données et aucun des deux threads ne doit se soucier des données modifiées par l'autre thread pendant qu'il l'utilise.
Certaines langues mélangent les deux modèles en offrant un stockage local par thread, avec ou sans système de type pour distinguer l'emplacement de stockage local par thread des emplacements globaux. Le stockage local par thread est généralement une fonctionnalité pratique qui permet à un nom de variable de désigner différents emplacements de stockage dans différents threads.
Quelques suivis (difficiles) qui peuvent être intéressants pour comprendre ce que sont les fils:
- Quel est le minimum qu'un noyau doit faire pour prendre en charge plusieurs threads?
- Dans un environnement multiprocesseur, que faut-il pour migrer un thread d'un processeur à un autre?
- Que faudrait-il pour implémenter le multithreading coopératif ( coroutines ) dans votre langage de programmation préféré sans prise en charge par le système d'exploitation et sans utiliser sa prise en charge intégrée le cas échéant? (Attention, la plupart des langages de programmation n'ont pas les primitives nécessaires pour implémenter des coroutines dans un seul thread.)
- À quoi pourrait ressembler un langage de programmation s'il avait une concurrence mais pas de concept (explicite) de threads? (Premier exemple: le pi-calcul .)