Mutex en Java

Haider Ali 15 février 2024
  1. Threading et multithreading
  2. Les threads en Java
  3. Mutex
  4. Explication
Mutex en Java

Dans le monde de l’informatique, l’exclusion mutuelle ou Mutex est connue comme une propriété de contrôle de la concurrence. Chaque ordinateur utilise la plus petite séquence d’instructions programmées appelée thread. À un moment donné, l’ordinateur fonctionne sur un seul thread. Plongeons-nous dans d’autres aspects pour une meilleure compréhension.

Threading et multithreading

Le processeur fonctionne sur les threads pour le multitâche. Chaque processus fonctionne en passant constamment d’un fil à l’autre à une vitesse très rapide. Par exemple, lorsque nous regardons une vidéo, l’audio de la vidéo est sur un fil différent et l’image sur un autre. Le basculement constant entre ces deux éléments est très rapide et est connu sous le nom de multithreading.

Les threads en Java

La création d’un thread en Java se fait en étendant une classe et en implémentant une interface. Le multithreading est une fonctionnalité Java qui permet l’exécution simultanée de deux ou plusieurs parties d’un programme afin de maximiser l’efficacité du processeur. Un thread est un composant d’un tel programme. Les threads sont donc des processus légers au sein des processus.

Mutex

Deux threads ou plus peuvent avoir besoin d’accéder simultanément à une ressource partagée dans un programme multithread, ce qui entraîne un comportement inattendu. Les structures de données, les périphériques d’entrée-sortie, les fichiers et les connexions réseau sont des exemples de ressources partagées.

C’est ce qu’on appelle une condition de course. La section clé du programme est la partie du programme qui accède à la ressource partagée. En conséquence, nous devons synchroniser l’accès à la partie critique pour éviter une condition de concurrence.

Le type de synchroniseur le plus basique est un mutex (ou exclusion mutuelle), qui garantit qu’un seul thread peut exécuter la zone essentielle d’un programme informatique à la fois. Il est implémenté par une classe appelée semaphore.

Un thread obtient le mutex, puis accède à la section cruciale et libère enfin le mutex pour accéder à une région critique. Pendant ce temps, tous les autres threads sont bloqués jusqu’à ce que le mutex soit libéré. Un thread peut entrer dans la section critique dès qu’il sort de la zone critique.

Pour mutex, il existe deux méthodes de verrouillage et de déverrouillage. Ils sont respectivement appelés acquire() et release(). Maintenant, regardez l’exemple ci-dessous.

En savoir plus sur Mutex ici.

import java.util.LinkedList; // linked list import
import java.util.concurrent.Semaphore; // semaphore import
public class Mutex {
  static LinkedList<String> WorkingQueue = new LinkedList<String>();
  // track the record of works
  static Semaphore mutex1 = new Semaphore(0); // creating a Semaphore To ImplementLogic
  static Semaphore mutex = new Semaphore(1); // Creating A Mutex
}

Dans l’exemple ci-dessus, nous avons créé deux objets Mutex portant le nom de mutex et mutex1. Nous utiliserons mutex1 pour contrôler le basculement entre deux threads. La raison de la création de la LinkedList est d’avoir un historique des discussions. Maintenant, ajoutons deux threads dans le code ci-dessus. Deux threads avec le nom de Producer et Consumer.

import java.util.LinkedList; // linked list import
import java.util.concurrent.Semaphore; // semaphore import
public class Mutex {
  static LinkedList<String> WorkingQueue = new LinkedList<String>();
  // track the record of works
  static Semaphore mutex1 = new Semaphore(0); // creating a Semaphore To ImplementLogic
  static Semaphore mutex = new Semaphore(1); // Creating A Mutex
  static class Producer extends Thread {
    public void run() { // default run method of thread
      int counter = 1;
      try {
        while (true) {
          String threadName = Thread.currentThread().getName()
              + counter++; // counter is added to have the thread number being used

          mutex.acquire(); // Acquiring  Lock  before Producing so the consumer cannot consume.
          WorkingQueue.add(threadName);
          System.out.println("Producer is prdoucing producing: " + threadName);
          mutex.release(); // releasing After Production ;
          mutex1.release(); // relesing lock for consumer...so consumer can consume after production
          Thread.sleep(2000); // just to Reduce the Execution Speed
        }
      } catch (Exception e) { /*nothing */
      }
    }
  }
  static class Consumer extends Thread {
    String consumerName;
    public Consumer(String name) {
      this.consumerName = name;
    }
    public void run() {
      try {
        while (true) {
          mutex1.acquire(); /// Again Acquiring So no production while consuming
          mutex.acquire(); // Acquring Other consumers lock one consume at one time
          String result = "";
          for (String value : WorkingQueue) {
            result = value + ",";
          }
          System.out.println(consumerName + " consumes value: " + result
              + "Total Size working Queue Size " + WorkingQueue.size() + "\n");
          mutex.release(); // releasing lock for other consumers.
        }
      } catch (Exception e) {
      }
    }
    public static void main(String[] args) {
      Producer producer = new Producer();

      producer.start();
      Consumer c1 = new Consumer("Bill Gates");
      Consumer c2 = new Consumer("Jeff Bezoz");
      Consumer c3 = new Consumer("Mark Zukerberg");
      c1.start();
      c2.start();
      c3.start();
    }
  }
}

Explication

Le code ci-dessus est également explicite, mais cette explication résoudra la confusion.

Dans le fil Producer

Lorsque vous exécutez le programme ci-dessus, il crée un fil de discussion producer. À l’intérieur de ce fil, il y a une boucle while qui s’exécutera indéfiniment. La chaîne threadName sert uniquement à afficher l’exécution du thread. L’objet mutex acquerra le verrou pour que le thread consommateur soit fonctionnel. (L’objectif principal de Mutex, obtenir le contrôle de la concurrence).

Après cela, le fil producer devient fonctionnel. Ensuite, nous devons libérer ce fil pour la production. Dans le thread producer, nous allons libérer mutex1, l’objet chargé de gérer le basculement entre consumer et producer. A la sortie, les consommateurs commenceront à consommer, c’est-à-dire que le fil consumer sera fonctionnel.

Dans le fil Consumer

Juste après être entré dans le fil consumer, nous avons acquis mutex1 pour arrêter la production pendant la consommation. Comme vous pouvez le constater, nous avons créé trois consommateurs sous les noms C1, C2 et C3. Afin de permettre à un seul consommateur d’être fonctionnel à la fois, nous avons également acquis mutex.

Après cela, C1 deviendra fonctionnel, tandis que C2 et C3 seront acquis. Une fois terminé, mutex sera à nouveau libéré, permettant à l’autre consommateur d’être fonctionnel.

C’est ainsi que fonctionne le mutex en Java. Après avoir exécuté le programme ci-dessus. Il affichera en permanence le nombre actuel de threads producer utilisés et le nom du consumer qui l’utilise.

exemple de mutex java

La taille continuera d’augmenter au fur et à mesure que le programme s’exécute.

Auteur: Haider Ali
Haider Ali avatar Haider Ali avatar

Haider specializes in technical writing. He has a solid background in computer science that allows him to create engaging, original, and compelling technical tutorials. In his free time, he enjoys adding new skills to his repertoire and watching Netflix.

LinkedIn

Article connexe - Java Threading