Les threads (class Thread
) sont appelés processus légers
car à la différence du fork d'Unix ils ne dupliquent pas l'état
mémoire du processus. L'intérêt d'utiliser des processus légers est
d'apporter une nouvelle manière d'exprimer un problème au programmeur.
Cela permet de mieux organiser son programme en différents threads. Dans
le cas où deux processus légers ne modifient pas un même état
mémoire il n'y a pas de risque de les employer. Dans l'autre cas on
tombe sur les problèmes classiques de section critique où les processus
doivent se synchroniser pour travailler correctement.
Pour lancer un processus, il faut créer un objet de la classe Thread
,
puis démarrer son exécution en invoquant la méthode start.
La méthode start appelle la méthode run. Il suffit alors
de redéfinir run dans sa sous-classe de Thread
pour implanter
un nouveau traitement.
Pour éviter les accès concurrents à la même donnée (un processus écrit
pendant qu'un autre lit), il est possible de s'assurer l'accès exclusif
à cette donnée. On bloque un objet soit en invoquant une méthode synchronized
sur l'objet, soit en utilisant l'instruction synchronized
sur un objet (avec le code associé qui suit).
Pour communiquer entre les threads, on emploie les méthodes wait
qui
attend qu'une condition soit remplie pour continuer,
en libérant les accès réservés, et notify
qui indique aux threads
en attente qu'une modification possible des conditions d'attente a été réalisée.
La méthode wait doit être utilisée à l'intérieur d'un bloc de
synchronisation, c'est à dire quand le processus a l'accès à l'objet.
Dans ce cas, le processus libère l'accès à l'objet et se met en attente. Pour le sortir
de cette attente, il faut qu'un autre processus exécute un notify() sur
cet objet et que lui-même
obtienne à nouveau l'accès exclusif à l'objet.
Les méthodes wait et notify existent pour tout objet. Elles ne peuvent être
appelées que lorsque le processus possède un accès exclusif à l'objet. La gestion
des accès concurrents fonctionne seulement pour les objets et non pour les types de base
(comme les entiers).
Tout ceci n'enlève pas les risques de blocage en cas d'attente sur des
ressources différentes.