Synchronisation des threads en Java

16 Sep 2019 16 Sep 2019 7660 vues ESSADDOUKI Mostafa 6 min de lecture
Introduction
1 Nouveautés de Java 11 2 Différences entre JDK, JRE et JVM 3 Structure d'un programme Java - Hello World 4 Mots clés et conventions de dénomination en Java 5 Types de données intégrés en Java 6 Les variables en Java 7 Classes enveloppe - Number, Integer, Double ... 8 Lire les entrées clavier en Java
Structures de contrôle
9 Les opérateurs en Java 10 Les structures conditionnelles en Java 11 Les boucles en Java 12 Instructions de contrôle de boucle - break, continue
Chaines de caractères
13 Les chaines en Java - API String 14 Les chaines en Java - StringBuffer et StringBuilder 15 Les expressions régulières en Java
Programmation OO
16 Objets et classes en Java 17 Modificateurs d'accès Java - public, private, protected et package 18 Méthodes et surcharge des méthodes en Java 19 les constructeurs en Java 20 L'héritage en Java 21 Classes abstraites en Java 22 Interfaces et héritage multiple en Java 23 Les classes imbriquées en Java 24 Les singletons en Java 25 Classes et méthodes génériques 26 Interface fonctionnelle et expressions Lambda en Java
Tableaux et collections
27 Les tableaux en Java 28 Classe Arrays - java.util.Arrays 29 Les listes dynamiques - java.util.ArrayList 30 Les listes chaînées en Java - java.util.LinkedList 31 HashSet en Java - java.util.HashSet 32 HashMap en Java - java.util.HashMap
Gestion des fichiers
33 Comprendre les fichiers informatiques 34 Utilisation des classes Path et Files en Java 35 Lecture et écriture dans un fichier en Java 36 Fichiers à accès aléatoire en Java
Gestion d'exceptions
37 Gestion d'exceptions en Java 38 Créez vos propres classes d'exception en Java
Programmation concurrente
39 Introduction à la programmation concurrente en Java - Multi-threads 40 classe java.lang.Thread 41 Synchronisation des threads en Java
Cours Java pour les débutants — Étape 41 sur 41

Lorsque nous démarrons deux ou plusieurs threads dans un programme, il peut arriver que plusieurs threads essaient d'accéder à la même ressource et qu'ils puissent finalement produire des résultats imprévus en raison de problèmes de concurrence. Par exemple, si plusieurs threads essaient d'écrire dans le même fichier, ils risquent de corrompre les données, car l'un des threads peut remplacer les données ou lorsqu'un thread ouvre le même fichier en même temps qu'un autre peut fermer le même fichier.

Il est donc nécessaire de synchroniser l'action de plusieurs threads et de vous assurer qu'un seul thread peut accéder à la ressource à un moment donné. Ceci est mis en œuvre en utilisant un concept appelé moniteurs. Chaque objet en Java est associé à un moniteur, qu'un thread peut verrouiller ou déverrouiller. Un seul thread à la fois peut verrouiller un moniteur.

Le langage de programmation Java offre un moyen très pratique de créer des threads et de synchroniser leur tâche à l’aide de blocs synchronized. Vous conservez des ressources partagées dans ce bloc.

Syntaxe :
                                synchronized(objectidentifier) {
                                    // Accéder aux variables partagées et autres ressources partagées
                                }
                            

Ici Objectidentifier est une référence à un objet dont le verrou est associé au moniteur représenté par l'instruction synchronized.

Exemple 1 :

Voici un exemple simple qui peut ou non d'afficher la valeur du compteur en séquence et chaque fois que nous l'exécutons, il produit un résultat différent en fonction de la disponibilité du processeur pour un thread.

                                    class Compteur {
                                        public void afficher() {
                                            try {
                                                for (int i = 10; i >= 0; i--) {
                                                    System.out.println("i = " + i);
                                                }
                                            } catch (Exception e) {
                                                System.out.println("Thread  interrompu.");
                                            }
                                        }
                                    }
                                    
                                    class Multithreading implements Runnable {
                                        Compteur cpt;
                                    
                                        public Multithreading(Compteur cpt) {
                                            this.cpt = cpt;
                                        }
                                    
                                        public void run() {
                                            cpt.afficher();
                                            System.out.println("Bye bye " + Thread.currentThread().getName());
                                        }
                                    }
                                    
                                    // classe principale
                                    public class Multithread {
                                        public static void main(String[] args) {
                                            Compteur cpt = new Compteur();
                                            Thread obj1 = new Thread(new Multithreading(cpt));
                                            Thread obj2 = new Thread(new Multithreading(cpt));
                                            obj1.start();
                                            obj2.start();
                                    
                                            // attendre la fin des threads
                                            try {
                                                obj1.join();
                                                obj1.join();
                                            } catch (Exception e) {
                                            }
                                        }
                                    }
                            
i = 4
i = 4
i = 3
i = 3
i = 2
i = 2
i = 1
i = 1
i = 0
i = 0
Bye bye Thread-1
Bye bye Thread-0
Exemple 2 :

Voici le même exemple qui affiche la valeur du compteur en séquence et chaque fois que nous l’exécutons, le résultat est identique.

                                    class Compteur {
                                        public void afficher() {
                                            try {
                                                for (int i = 4; i >= 0; i--) {
                                                    System.out.println("i = " + i);
                                                }
                                            } catch (Exception e) {
                                                System.out.println("Thread  interrompu.");
                                            }
                                        }
                                    }
                                    
                                    class Multithreading implements Runnable {
                                        Compteur cpt;
                                    
                                        public Multithreading(Compteur cpt) {
                                            this.cpt = cpt;
                                        }
                                    
                                        public void run() {
                                            synchronized (cpt) {
                                                cpt.afficher();
                                            }
                                            System.out.println("Bye bye " + Thread.currentThread().getName());
                                        }
                                    }
                                    
                                    // classe principale
                                    public class Multithread {
                                        public static void main(String[] args) {
                                            Compteur cpt = new Compteur();
                                            Thread obj1 = new Thread(new Multithreading(cpt));
                                            Thread obj2 = new Thread(new Multithreading(cpt));
                                            obj1.start();
                                            obj2.start();
                                    
                                            // attendre la fin des threads
                                            try {
                                                obj1.join();
                                                obj1.join();
                                            } catch (Exception e) {
                                            }
                                        }
                                    }
                            
i = 4
i = 3
i = 2
i = 1
i = 0
i = 4
i = 3
i = 2
i = 1
i = 0
Bye bye Thread-1
Bye bye Thread-0

Dans l'exemple ci-dessus, nous avons choisi de synchroniser l'objet Compteur dans la méthode run() de la classe Multithreading. Alternativement, nous pourrions définir l'ensemble du bloc de la méthode afficher() comme étant synchronisé et produire le même résultat.

Les points importants

  •   Lorsqu'un thread entre dans une méthode ou un bloc synchronisé, il acquiert un verrou et une fois qu'il a terminé sa tâche et qu'il quitte la méthode synchronisée, il libère le verrou.
  •   Lorsque le thread entre dans une méthode ou un bloc d'instance synchronisée, il acquiert un verrou de niveau objet et lorsqu'il entre dans une méthode ou un bloc statique synchronisé, il acquiert un verrou de niveau de classe.
  •   La synchronisation Java lève une exception NullPointerException si l'objet utilisé dans un bloc synchronisé est nul. Par exemple, si dans synchronized (instance), instance est null, elle lève une exception NullPointerException.
  •   En Java, wait(), notify() et notifyAll() sont les méthodes importantes utilisées dans la synchronisation.
  •   Vous ne pouvez pas appliquer le mot clé java synchronized aux variables.
  •   Ne synchronisez pas sur le champ non final du bloc synchronisé, car la référence au champ non final peut changer à tout moment et différents threads peuvent alors se synchroniser sur différents objets, c’est-à-dire qu’il n’ya aucune synchronisation.

Avantages de la Synchronisation

  •   Multithreading: comme Java est un langage multithread, la synchronisation est un bon moyen de parvenir à une exclusion mutuelle sur les ressources partagées.
  •   Méthodes d'instance et statiques: les méthodes d'instance synchronisées et les méthodes statiques synchronisées peuvent être exécutées simultanément car elles sont utilisées pour verrouiller différents objets.

Limites de la Synchronisation

  •   Limitations de la simultanéité: la synchronisation Java n'autorise pas les lectures simultanées.
  •   Diminution de l'efficacité: la méthode synchronized s'exécute très lentement et peut dégrader les performances. Vous devez donc synchroniser la méthode lorsque cela est absolument nécessaire et ne synchroniser le bloc que pour la section critique du code.

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.