0% ont trouvé ce document utile (0 vote)
29 vues17 pages

Creation Thread

Ce document aborde les problèmes fondamentaux de la programmation parallèle, tels que les conditions de course, l'interblocage et la famine, en fournissant des exemples de code en Java. Chaque problème est expliqué en détail, avec des solutions proposées pour aider les débutants à comprendre les concepts. Des exercices pratiques sont également inclus pour renforcer l'apprentissage.

Transféré par

stephan tincho
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
29 vues17 pages

Creation Thread

Ce document aborde les problèmes fondamentaux de la programmation parallèle, tels que les conditions de course, l'interblocage et la famine, en fournissant des exemples de code en Java. Chaque problème est expliqué en détail, avec des solutions proposées pour aider les débutants à comprendre les concepts. Des exercices pratiques sont également inclus pour renforcer l'apprentissage.

Transféré par

stephan tincho
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Problèmes de Programmation Parallèle pour Débutants

Université de Rennes 1
24 janvier 2026

Table des matières


Introduction 2

1 Qu’est-ce qu’un thread ? 2

2 Problème 1 : Condition de course (Race Condition) 3


2.1 Description du problème . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Explication ligne par ligne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Scénario problématique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.4 Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

3 Problème 2 : Interblocage (Deadlock) 8


3.1 Description du problème . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2 Explication ligne par ligne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3 Diagramme d’interblocage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.4 Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

4 Problème 3 : Famine (Starvation) 12


4.1 Description du problème . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4.2 Explication ligne par ligne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.3 Analyse des temps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.4 Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

5 Récapitulatif des problèmes 16

6 Exercices pratiques 16
6.1 Exercice 1 : Détecter la condition de course . . . . . . . . . . . . . . . . . . . . . 16
6.2 Exercice 2 : Éviter l’interblocage . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
6.3 Exercice 3 : Observer la famine . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Conclusion 16

Pour aller plus loin 17

1
Introduction
Ce document présente les problèmes fondamentaux de la programmation parallèle de ma-
nière simple et progressive. Chaque exemple est accompagné d’explications détaillées de chaque
ligne de code, spécialement conçu pour des étudiants débutants en Java.

1 Qu’est-ce qu’un thread ?


1 public class PremierThread {
2 public static void main ( String [] args ) {
3 // Ligne 1: C r a t i o n d ’ un thread
4 Thread monThread = new Thread (() -> {
5 // Ligne 2: Ce code s ’ e x c u t e en p a r a l l l e
6 System . out . println ( " Je suis dans un thread ! " ) ;
7 }) ;
8
9 // Ligne 3: D m a r r a g e du thread
10 monThread . start () ;
11
12 // Ligne 4: Code du thread principal
13 System . out . println ( " Je suis dans le main " ) ;
14 }
15 }

Listing 1 – Création simple d’un thread

Explication détaillée des lignes de code


— Ligne 1 : Thread monThread = new Thread(() -> {...})
— Thread : Classe qui représente un thread (fil d’exécution)
— monThread : Variable qui va contenir notre thread
— new Thread(...) : Création d’un nouvel objet Thread
— () -> {...} : Expression lambda (code à exécuter)
— Ligne 2 : [Link]("Je suis dans un thread!")
— Affiche un message quand le thread s’exécute
— Ce code tourne en parallèle du main
— Ligne 3 : [Link]()
— start() : Démarre le thread (NE PAS utiliser run())
— Après cette ligne, deux codes s’exécutent en même temps
— Ligne 4 : [Link]("Je suis dans le main")
— Code du programme principal
— S’exécute en parallèle du thread

2
2 Problème 1 : Condition de course (Race Condition)
2.1 Description du problème
Notes sur le code
Une condition de course se produit quand plusieurs threads lisent et modifient la même
variable en même temps, sans coordination.

1 public class ConditionCourse {


2 // Ligne 1: Variable p a r t a g e
3 static int argent = 1000;
4
5 public static void main ( String [] args ) throws Exception {
6 System . out . println ( " === Condition de course === " ) ;
7
8 // Ligne 2: Affichage initial
9 System . out . println ( " Argent initial : " + argent ) ;
10
11 // Lignes 3 -4: C r a t i o n des threads
12 Thread alice = new Thread ( new Client ( " Alice " ) ) ;
13 Thread bob = new Thread ( new Client ( " Bob " ) ) ;
14
15 // Lignes 5 -6: D m a r r a g e
16 alice . start () ;
17 bob . start () ;
18
19 // Lignes 7 -8: Attente
20 alice . join () ;
21 bob . join () ;
22
23 // Ligne 9: R s u l t a t
24 System . out . println ( " Argent final : " + argent ) ;
25 }
26
27 // Ligne 10: Classe Client
28 static class Client implements Runnable {
29 String nom ;
30
31 // Ligne 11: Constructeur
32 Client ( String nom ) {
33 this . nom = nom ;
34 }
35
36 // Ligne 12: M t h o d e run
37 public void run () {
38 // Ligne 13: V r i f i c a t i o n
39 if ( argent >= 1000) {
40 // Ligne 14: Simulation d ’ un d l a i
41 try { Thread . sleep (10) ; }
42 catch ( Exception e ) {}
43
44 // Ligne 15: Retrait d ’ argent
45 argent = argent - 1000;
46
47 // Ligne 16: Affichage
48 System . out . println ( nom + " a r e t i r 1000 ");
49 }
50 }

3
51 }
52 }

Listing 2 – Condition de course avec un compte bancaire

4
5
2.2 Explication ligne par ligne
Explication détaillée
Ligne 1 : static int argent = 1000;
— static : La variable existe pour toute la classe
— int : Type entier
— argent : Nom de la variable
— = 1000 : Valeur initiale (1000 euros)
— Problème : Cette variable est partagée par tous les threads
Ligne 2 : [Link]("Argent initial: " + argent);
— Affiche le contenu initial de la variable
— Résultat : "Argent initial : 1000"
Ligne 3 : Thread alice = new Thread(new Client("Alice"));
— Crée un thread pour Alice
— new Client("Alice") : Crée un objet Client
— new Thread(...) : Transforme en Thread
Ligne 4 : Thread bob = new Thread(new Client("Bob"));
— Même chose pour Bob
— Maintenant on a 2 threads prêts
Ligne 5 : [Link]();
— Démarre le thread d’Alice
— IMPORTANT : start() pas run()
Ligne 6 : [Link]();
— Démarre le thread de Bob
— Maintenant 3 threads tournent : main, Alice, Bob
Ligne 7 : [Link]();
— join() : Attend qu’Alice termine
— Le main s’arrête ici jusqu’à ce qu’Alice finisse
Ligne 8 : [Link]();
— Attend que Bob termine
— Après cette ligne, tous les threads sont finis
Ligne 9 : [Link]("Argent final: " + argent);
— Affiche le résultat final
— Problème : affiche parfois -1000 au lieu de 0
Ligne 10 : static class Client implements Runnable
— static : Classe interne statique
— class Client : Définition de la classe Client
— implements Runnable : Cette classe peut devenir un thread
Ligne 11 : Client(String nom) { [Link] = nom; }
— Constructeur de la classe Client
— [Link] = nom : Stocke le nom dans l’objet
Ligne 12 : public void run()
— Méthode obligatoire quand on implémente Runnable
6
— C’est ici qu’on met le code du thread
2.3 Scénario problématique
Temps Thread Alice Thread Bob
t=0 Vérifie : argent=1000 (OK) Vérifie : argent=1000 (OK)
t=10ms Dort (sleep) Dort (sleep)
t=20ms argent=1000-1000=0 Se réveille
t=30ms Affiche "Alice a retiré" argent=0-1000=-1000
t=40ms Finit Affiche "Bob a retiré"

2.4 Solution
1 public synchronized void retirer () {
2 if ( argent >= 1000) {
3 argent -= 1000;
4 }
5 }

Listing 3 – Solution avec synchronized

Explication détaillée de la solution


— synchronized : Un seul thread à la fois peut entrer
— Quand Alice est dans la méthode, Bob attend
— Quand Alice sort, Bob peut entrer
— Résultat garanti : argent = 0

7
3 Problème 2 : Interblocage (Deadlock)
3.1 Description du problème
Notes sur le code
Un interblocage se produit quand deux threads s’attendent mutuellement. Chacun dé-
tient une ressource dont l’autre a besoin.

1 public class Interblocage {


2 // Lignes 1 -2: Deux ressources
3 static Object stylo = new Object () ;
4 static Object cahier = new Object () ;
5
6 public static void main ( String [] args ) {
7 System . out . println ( " === Interblocage === " ) ;
8
9 // Ligne 3: Thread 1
10 Thread eleve1 = new Thread (() -> {
11 // Ligne 4: Prend le stylo
12 synchronized ( stylo ) {
13 System . out . println ( " lve 1 a le stylo " ) ;
14
15 // Ligne 5: Petite pause
16 try { Thread . sleep (100) ; }
17 catch ( Exception e ) {}
18
19 // Ligne 6: Essaye de prendre le cahier
20 synchronized ( cahier ) {
21 System . out . println ( " lve 1 a le cahier " ) ;
22 }
23 }
24 }) ;
25
26 // Ligne 7: Thread 2
27 Thread eleve2 = new Thread (() -> {
28 // Ligne 8: Prend le cahier
29 synchronized ( cahier ) {
30 System . out . println ( " lve 2 a le cahier " ) ;
31
32 // Ligne 9: Petite pause
33 try { Thread . sleep (100) ; }
34 catch ( Exception e ) {}
35
36 // Ligne 10: Essaye de prendre le stylo
37 synchronized ( stylo ) {
38 System . out . println ( " lve 2 a le stylo " ) ;
39 }
40 }
41 }) ;
42
43 // Lignes 11 -12: D m a r r a g e
44 eleve1 . start () ;
45 eleve2 . start () ;
46 }
47 }

Listing 4 – Interblocage avec deux ressources

8
9
3.2 Explication ligne par ligne
Explication détaillée
Ligne 1 : static Object stylo = new Object();
— Crée un objet "stylo"
— Object : Type le plus simple en Java
— Sera utilisé comme ressource à partager
Ligne 2 : static Object cahier = new Object();
— Crée un objet "cahier"
— Deuxième ressource à partager
Ligne 3 : Thread eleve1 = new Thread(() -> { ... });
— Crée le premier élève (thread 1)
— Utilise une lambda pour le code
Ligne 4 : synchronized (stylo) { ... }
— synchronized : Prend le verrou sur "stylo"
— Pendant ce bloc, personne d’autre ne peut prendre "stylo"
— Élève 1 détient maintenant le stylo
Ligne 5 : try [Link](100); catch (Exception e) {}
— Pause de 100ms
— Simule un temps de traitement
— Important : Pendant ce temps, élève 2 peut agir
Ligne 6 : synchronized (cahier) { ... }
— Essaye de prendre le cahier
— PROBLÈME : Élève 2 a peut-être déjà pris le cahier
— Si c’est le cas, élève 1 attend indéfiniment
Ligne 7 : Thread eleve2 = new Thread(() -> { ... });
— Crée le deuxième élève
— Code symétrique mais ordre inverse
Ligne 8 : synchronized (cahier) { ... }
— Élève 2 prend le cahier en premier
— Ordre différent d’élève 1
Ligne 9 : try [Link](100); catch (Exception e) {}
— Même pause qu’élève 1
— Les deux threads dorment en même temps
Ligne 10 : synchronized (stylo) { ... }
— Essaye de prendre le stylo
— PROBLÈME : Élève 1 a déjà le stylo
— Si c’est le cas, élève 2 attend indéfiniment
Ligne 11 : [Link]();
— Démarre élève 1
— Élève 1 prend le stylo
Ligne 12 : [Link]();
— Démarre élève 2
10
— Élève 2 prend le cahier
— Résultat : Chacun attend ce que l’autre a
3.3 Diagramme d’interblocage

Élève 1 Élève 2
attend attend
détient détient
Stylo Cahier

3.4 Solution
1 // lve 1 ET lve 2 prennent dans le m m e ordre
2 synchronized ( stylo ) {
3 synchronized ( cahier ) {
4 // Travail
5 }
6 }

Listing 5 – Solution : toujours prendre dans le même ordre

11
4 Problème 3 : Famine (Starvation)
4.1 Description du problème
Notes sur le code
La famine se produit quand un thread n’arrive jamais à accéder à une ressource parce
que d’autres threads l’utilisent toujours.

1 public class Famine {


2 // Ligne 1: Un seul ordinateur
3 static Object ordinateur = new Object () ;
4
5 public static void main ( String [] args ) throws Exception {
6 System . out . println ( " === Famine === " ) ;
7
8 // Ligne 2: Le prof ( utilise beaucoup )
9 Thread prof = new Thread (() -> {
10 while ( true ) {
11 // Ligne 3: Prend l ’ ordinateur
12 synchronized ( ordinateur ) {
13 // Ligne 4: Utilisation longue
14 System . out . println ( " PROF utilise " ) ;
15 try { Thread . sleep (200) ; }
16 catch ( Exception e ) {}
17 }
18 // Ligne 5: Petite pause avant de reprendre
19 try { Thread . sleep (50) ; }
20 catch ( Exception e ) {}
21 }
22 }) ;
23
24 // Ligne 6: L ’ lve ( veut juste un peu )
25 Thread eleve = new Thread (() -> {
26 while ( true ) {
27 // Ligne 7: Essaye de prendre l ’ ordinateur
28 synchronized ( ordinateur ) {
29 // Ligne 8: Utilisation courte
30 System . out . println ( " lve utilise ( rare !) " ) ;
31 }
32 // Ligne 9: Attente avant de r e s s a y e r
33 try { Thread . sleep (100) ; }
34 catch ( Exception e ) {}
35 }
36 }) ;
37
38 // Lignes 10 -11: D m a r r a g e
39 prof . start () ;
40 eleve . start () ;
41
42 // Ligne 12: Attendre 3 secondes
43 Thread . sleep (3000) ;
44
45 // Ligne 13: R s u l t a t
46 System . out . println ( " \ n R s u l t a t : L ’ lve a t r s peu u t i l i s ! " ) ;
47 }
48 }

Listing 6 – Famine dans une salle d’ordinateurs

12
13
4.2 Explication ligne par ligne
Explication détaillée
Ligne 1 : static Object ordinateur = new Object();
— Ressource unique (1 ordinateur)
— Tous les threads veulent l’utiliser
Ligne 2 : Thread prof = new Thread(() -> { ... });
— Crée le thread du professeur
— Le prof utilise beaucoup l’ordinateur
Ligne 3 : synchronized (ordinateur) { ... }
— Prend l’ordinateur (verrou)
— Quand le prof est ici, personne d’autre ne peut utiliser l’ordi
Ligne 4 : [Link]("PROF utilise"); ... [Link](200);
— Simulation d’utilisation longue (200ms)
— Le prof garde l’ordinateur longtemps
Ligne 5 : try [Link](50); catch (Exception e) {}
— Pause de 50ms après avoir libéré
— Puis le prof reprend l’ordinateur très vite
— L’élève n’a pas le temps de prendre sa place
Ligne 6 : Thread eleve = new Thread(() -> { ... });
— Crée le thread de l’élève
— L’élève a moins de chance d’accéder à l’ordi
Ligne 7 : synchronized (ordinateur) { ... }
— L’élève essaye de prendre l’ordinateur
— Problème : Le prof l’a presque toujours
— Quand l’élève arrive, l’ordi est déjà pris
Ligne 8 : [Link]("élève utilise (rare!)");
— Affiche quand l’élève réussit
— Ce message apparaît très rarement
Ligne 9 : try [Link](100); catch (Exception e) {}
— L’élève attend 100ms avant de réessayer
— Plus long que le prof (50ms)
— Le prof a donc plus de chances
Ligne 10 : [Link]();
— Démarre le professeur
— Le prof commence à utiliser l’ordinateur
Ligne 11 : [Link]();
— Démarre l’élève
— L’élève essaye d’accéder à l’ordinateur
Ligne 12 : [Link](3000);
— Laisse tourner le programme 3 secondes
— Pour observer le phénomène
Ligne 13 : [Link]("\nRésultat: ...");
14
— Affiche le constat
4.3 Analyse des temps
Acteur Temps utilisation Temps attente
Professeur 200ms 50ms
Élève (quand il peut) 100ms

Calcul :
— Cycle professeur : 200ms (utilisation) + 50ms (pause) = 250ms
— Dans un cycle, fenêtre pour élève : seulement 50ms
— L’élève vérifie toutes les 100ms
— Probabilité que l’élève trouve l’ordi libre : très faible

4.4 Solution
1 // Utiliser une file d ’ attente quitable
2 ReentrantLock lock = new ReentrantLock ( true ) ; // true = quitable
3 lock . lock () ;
4 try {
5 // utilisation
6 } finally {
7 lock . unlock () ;
8 }

Listing 7 – Solution avec priorité équitable

15
5 Récapitulatif des problèmes

Problème Analogie réelle Symptôme Solution simple


Condition de Deux personnes voient Données incorrectes synchronized
course "1 place" et prennent
la place
Interblocage "Donne-moi X, je te Programme bloqué Même ordre des ver-
donne Y" (x2) rous
Famine Grand frère sur la Un thread n’agit ja- Priorités équitables
console, petit jamais mais

Table 1 – Récapitulatif des trois problèmes principaux

6 Exercices pratiques
6.1 Exercice 1 : Détecter la condition de course
1. Modifiez le programme de condition de course :
2. Changez le montant à retirer (500 au lieu de 1000)
3. Lancez 4 threads au lieu de 2
4. Observez le résultat final
5. Calculez ce qui devrait être le bon résultat

6.2 Exercice 2 : Éviter l’interblocage


1. Dans le programme d’interblocage :
2. Faites prendre les ressources dans le même ordre
3. Vérifiez que le programme ne se bloque plus
4. Ajoutez une troisième ressource
5. Gardez le même ordre pour tous

6.3 Exercice 3 : Observer la famine


1. Dans le programme de famine :
2. Changez les temps de sleep
3. Mesurez combien de fois l’élève réussit
4. Ajoutez un troisième thread (technicien)
5. Donnez des priorités différentes

Conclusion
Ces exemples simples montrent les problèmes fondamentaux de la programmation parallèle.
La clé est de toujours se souvenir que plusieurs threads peuvent s’exécuter en même temps et
doivent partager les ressources proprement.
— Règle 1 : Synchronisez l’accès aux données partagées
— Règle 2 : Prenez toujours les verrous dans le même ordre
— Règle 3 : Soyez équitables dans l’accès aux ressources

16
Pour aller plus loin
— Java Concurrency in Practice : Livre de référence
— Tutoriels Oracle : [Link]
— Exemples avancés : Producteur-Consommateur, Lecteurs-Rédacteurs
— API [Link] : Classes pour la concurrence

17

Vous aimerez peut-être aussi