Récapitulatif : les compromis du multithread
Maintenant qu'on a vu le parallélisme et le multithread, voici les compromis à garder en tête pour faire les bons choix.
stream() vs parallelStream()
stream() | parallelStream() | |
|---|---|---|
| Overhead | Aucun | Création/fusion des threads |
| Efficace si | Opérations légères ou petits volumes | Opérations CPU-intensives sur gros volumes |
| Thread-safe requis | Non | Oui |
| Risques | Aucun | Race conditions si état partagé |
parallelStream() n'est pas automatiquement plus rapide — il faut que le travail par élément soit suffisamment coûteux pour amortir l'overhead de coordination.
.parallel() vs .parallelStream()
| Sur quoi c'est appelé | Exemple | |
|---|---|---|
.parallelStream() | Une Collection (List, Set...) | list.parallelStream() |
.parallel() | Un Stream déjà existant | IntStream.range(0, 1000).parallel() |
Le comportement final est identique dans les deux cas.
Synchronisé vs Non-synchronisé
| Synchronisé | Non-synchronisé | |
|---|---|---|
| Thread-safe | Oui | Non |
| Performance | Dégradée (verrous) | Maximale |
| Risques | Deadlock possible | Race conditions |
La synchronisation protège les données partagées mais a un coût en performance. L'objectif est de synchroniser le minimum nécessaire.
Problèmes liés au multithread
| Problème | Description | Symptôme |
|---|---|---|
| Race condition | Deux threads modifient la même donnée en même temps | Résultats imprévisibles ou incorrects |
| Deadlock | Deux threads s'attendent mutuellement | Programme gelé, ne termine jamais |
| Livelock | Deux threads se cèdent la place en boucle | Programme actif mais ne progresse pas |
| Starvation | Un thread n'obtient jamais le verrou | Un thread ne s'exécute presque jamais |
La loi d'Amdahl
L'amélioration maximale apportée par le parallélisme est limitée par la partie séquentielle du programme.
- Si 90 % du code est parallélisable et 10 % est séquentiel → gain maximal théorique : ×10, peu importe le nombre de cœurs.
- Plus la partie séquentielle est grande, moins le parallélisme est utile.
En résumé : quoi choisir?
| Situation | Recommandation |
|---|---|
| Traitement indépendant, CPU-intensif, gros volume | parallelStream() |
| État partagé entre threads | synchronized |
| Plusieurs verrous dans un même programme | Toujours les acquérir dans le même ordre |
| Données partagées en lecture seulement | Immutabilité (aucune synchronisation nécessaire) |