Vous êtes sur la page 1sur 23

Les Threads

(suite)
Synchronisation
• Lorsque 2 threads ou plus ont besoin d’une même ressource au
même moment, il y a besoin de s’assurer que la ressource ne sera
utilisée que par un thread en même temps : on utilise alors un
procédé de synchronisation.

• Un moyen d’obtenir une synchronisation : les moniteurs.

• Un moniteur est un mécanisme utilisé comme un verrou d’exclusion


mutuelle, un mutex.

2
Synchronisation
• Lorsqu’un thread acquiert un verrou, on dit qu’il entre dans le
moniteur.

• Les autres threads sont dits en attente du moniteur.

• Analogie avec des cabines d’essayage de vêtements.

• Deux moyens de synchronisation : les méthodes synchronisées et les


blocs synchronisés.
3
Communication inter-threads
• Pas besoin de scrutation entre threads.

• Exemple d’un producteur et d’un consommateur avec la contrainte


que le producteur doit attendre que le consommateur ait terminé
avant qu’il puisse générer des données supplémentaires.

• Dans un système avec scrutation, le consommateur perd des cycles


CPU à attendre que le producteur produise ; lorsque le producteur a
terminé, il perd des cycles CPU à attendre que le consommateur ait
terminé, et ainsi de suite.

4
Communication inter-threads
• La scrutation est évitée avec un mécanisme de communication inter-
threads accessible à travers 3 méthodes :
• La méthode wait() : fait sortir la tâche appelante du moniteur et la
met en sommeil jusqu’à ce qu’un autre thread entre dans le même
moniteur et appelle notify() ;
• La méthode notify() : réveille le premier thread ayant appelé wait()
sur le même objet ;
• La méthode notifyAll() : réveille touts les threads ayant appelé wait()
sur le même objet ; le thread de priorité la plus élevée s’exécutera en
premier.
5
États d’un thread et ordonnancement
• Un thread peut se trouver dans l’un des 7 états suivant :
• nouveau (new) Lorsqu’un nouveau thread est créé, par exemple avec
Thread th = new Thread(a).

• prêt (runnable) ou prêt à s’exécuter. Lorsque la méthode start() d’un


thread est appelée, cette dernière passe dans l’état prêt. Touts les
threads prêts d’un programme Java sont organisés par la machine
virtuelle en une structure de données nommée la file d’attente prête.
Un thread entrant dans l’état prêt est mis dans cette file. Le code de
la méthode run() sera appelé à l’exécution du thread.
6
États d’un thread et ordonnancement
• en cours d’exécution (running) Le thread se voit alloué des cycles CPU
par l’ordonnanceur. Si un thread dans l’état en cours d’exécution
appelle sa méthode yield(), ou si il est supplanté par un thread de
priorité plus élevée, il laisse la CPU et est remis dans la file d’attente
prête, entrant dans l’état prêt.
• suspendu (suspended) Un thread prêt ou en cours d’exécution entre
dans l’état suspendu lorsque sa méthode suspend() est appelée. Un
thread peut se suspendre lui-même ou l’être par un autre. De l’état
suspendu, un thread ré-entre dans l’état prêt lorsque sa méthode
resume() est appelée par un autre thread.

7
États d’un thread et ordonnancement
• bloqué (blocked) Un thread entre dans l’état bloqué lorsque :
• Il appelle sa méthode sleep(),
• Il appelle wait() dans une méthode synchronisée d’un objet,
• Il appelle join() sur un autre objet dont le thread ne s’est pas encore
• terminée,
• Il effectue une opération d’entrée/sortie bloquante (comme lire à
partir du clavier).
• À partir de l’état bloqué, un thread ré-entre dans l’état prêt.

8
États d’un thread et ordonnancement
• suspendu-bloqué (suspended-blocked) Losqu’un thread est bloqué
est suspendue par un autre thread. Si l’opération bloquante se
termine, le thread entre dans l’état suspendu. Si le thread est
réintégrée (resumed) avant que l’opération bloquante ne se termine,
il entre dans l’état bloqué.

• mort (dead) Un thread se termine et entre dans l’état mort lorsque sa


méthode run() se termine ou lorsque sa méthode stop() est appelée.

9
Ordonnancement
• L’ordonnanceur s’assure que le thread de plus haute priorité (ou les
s’il y en a plusieurs d’égale priorité) est exécuté par la CPU.

• Si un thread de plus haute priorité entre dans la file des threads prêts,
l’ordonnanceur de threads Java met le thread en cours dans la file
d’attente, pour que le prioritaire s’exécute.

• Le thread en cours est dit supplanté par préemption par le thread de


plus haute priorité.

11
Ordonnancement
• Si le thread en cours d’exécution passe la main (via yield() ), est
suspendue ou bloqué, l’ordonnanceur choisit dans la file d’attente
prête le thread de priorité la plus élevée (ou l’un d’entre eux si ils sont
plusieurs) pour être exécuté.

• Un autre aspect est le partage du temps. Un ordre de grandeur


courant pour un quantum de temps est 100 ms. En temps partagé, si
un thread en cours d’exécution n’a pas été stoppé, bloqué,
suspendue, ne s’est pas terminé, ou n’a pas passé la main, et s’il y a
d’autres threads de priorité égale dans la file d’attente prête, la CPU
est réallouée à l’un d’entre eux.

12
Threads utilisateurs vs Threads noyaux
Threads utilisateurs
• Les threads utilisateurs sont des threads qui ne sont pas liés au système
d'exploitation. Ceux-ci sont gérés à l'intérieur d'un processus, par une
bibliothèque logicielle. Celle-ci s'occupe de la création et la suppression
des threads, ainsi que de leur ordonnancement.

• Le système d'exploitation ne peut pas les ordonnancer et n'a donc pas


besoin de mémoriser les informations des threads.

• Par contre, chaque thread doit se partager le temps alloué au processus


lors de l'ordonnancement : c'est dans un quantum de temps que ces
threads peuvent s'exécuter.

13
Threads utilisateurs vs Threads noyaux
Threads utilisateurs

14
Threads utilisateurs vs Threads noyaux
Threads noyaux
• Les threads noyaux sont gérés par le système d'exploitation, qui peut
les créer, les détruire ou les ordonnancer.

• L'ordonnancement est donc plus efficace, vu que chaque thread est


ordonnancé tel quel. Il est donc nécessaire de disposer d'une table
des threads pour mémoriser les contextes d'exécution et les
informations de chaque thread.

15
Threads utilisateurs vs Threads noyaux
Threads noyaux

16
Avantages et Inconvénients de l’utilisation des
Threads
Avantages
• Economie d’espace mémoire et de temps à la
création et à la commutation : la création d’un thread
est rapide et très économique car elle ne nécessite qu’un
identificateur , un contexte machine et une pile (zone
dynamique pour les variables locales).

• Par exemple dans Solaris on estime qu’une création de


processus lourd met 30 fois plus de temps qu’une
création de thread ; et une commutation de contextes de
processus lourds est 5 fois plus lente que celle des
threads.
17
Avantages et Inconvénients de l’utilisation des
Threads
Avantages
• Partage des ressources : l’avantage de partager
les ressources du processus ,son code
exécutable, ses variables globales est de
permettre à toute application d’être traitée par
plusieurs threads partageant le même espace
adressable.

18
Avantages et Inconvénients de l’utilisation des
Threads
Avantages
• Réactivité : augmentation du degré d’interactivité des
applications : l’exécution d’une application interactive par
plusieurs threads lui permet de continuer à s’exécuter
même si une partie des threads est bloquée ou ralentie
par une opération longue.

• Plusieurs requêtes interactives peuvent ainsi s’exécuter


en parallèle. Par exemple un navigateur WEB exécuté par
plusieurs threads peut traiter plusieurs requêtes
interactives sur plusieurs pages WEB simultanément.

19
Avantages et Inconvénients de l’utilisation des
Threads
Avantages
• Accélération des applications et augmentation du
débit d’un système ou d’un serveur délivrant des
services sur un réseau.

• Les applications multithreads s’exécuteront encore


plus vite dans un environnement multiprocesseurs.

20
Avantages et Inconvénients de l’utilisation des
Threads
Inconvénients
• La principale difficulté dans l'utilisation des threads est la gestion des
accès aux ressources communes:
• L’accès aux données partagées : il n’y a aucune protection entre
threads. Contrairement aux processus lourds dont les espaces
d’adressage sont disjoints et dont les accès aux objets sont soumis à
un contrôle strict de la part du système, les threads créés par un
processus peuvent accéder sans restriction à tous les objets du
processus (par exemple un thread peut lire ,modifier et même
effacer complètement la pile d’un autre thread ).
• Le programmeur qui réalise une application multithreads devra donc
le faire avec beaucoup de soins (la mise au point peut être longue et
délicate).

21
Avantages et Inconvénients de l’utilisation des
Threads
Inconvénients
• La gestion des signaux : comment gérer les signaux par les
threads (qui reçoit et traite un signal : tous les threads, ou un
seul ? )

22
Avantages et Inconvénients de l’utilisation des
Threads
Inconvénients
• les threads permettent de paralléliser les applications
sur multiprocesseurs mais la synchronisation des accès à la
mémoire doit se faire avec soin pour garantir la cohérence
des données traitées et des résultats : d’où la nécessité
d’utiliser des outils de synchronisation et de mise au point
puissants.

23