Mutex en Java

Haider Ali 12 octubre 2023
  1. Subprocesos y subprocesos múltiples
  2. Hilos en Java
  3. Mutex
  4. Explicación
Mutex en Java

En el mundo de la informática, la exclusión mutua o Mutex se conoce como una propiedad del control de concurrencia. Cada computadora trabaja con la secuencia más pequeña de instrucción programada conocida como hilo. En un momento, la computadora funciona en un solo hilo. Profundicemos en algunos aspectos más para una mejor comprensión.

Subprocesos y subprocesos múltiples

La CPU funciona en subprocesos para realizar múltiples tareas. Cada proceso funciona cambiando constantemente de un hilo a otro a una velocidad muy rápida. Por ejemplo, cuando miramos un video, el audio del video está en un hilo diferente y la imagen está en otro diferente. El cambio constante entre estos dos es muy rápido y se conoce como multiproceso.

Hilos en Java

La creación de un hilo en Java se realiza ampliando una clase e implementando una interfaz. El subproceso múltiple es una característica de Java que permite la ejecución de dos o más partes de un programa simultáneamente para maximizar la eficiencia de la CPU. Un hilo es un componente de dicho programa. Los subprocesos son, por tanto, procesos ligeros dentro de los procesos.

Mutex

Es posible que dos o más subprocesos necesiten acceder a un recurso compartido simultáneamente en un programa multiproceso, lo que da como resultado un comportamiento inesperado. Las estructuras de datos, los dispositivos de entrada y salida, los archivos y las conexiones de red son ejemplos de recursos compartidos.

Se denomina condición de carrera. La sección clave del programa es la parte del programa que accede al recurso compartido. Como resultado, debemos sincronizar el acceso a la parte crítica para evitar una condición de carrera.

El tipo más básico de sincronizador es un mutex (o exclusión mutua), que asegura que solo un hilo puede ejecutar el área esencial de un programa de computadora a la vez. Está implementado por una clase llamada semaphore.

Un hilo obtiene el mutex, luego accede a la sección crucial y, por último, libera el mutex para acceder a una región crítica. Mientras tanto, todos los demás subprocesos se bloquean hasta que se libera el mutex. Un hilo puede entrar en la sección crítica tan pronto como sale del área crítica.

Para mutex, existen dos métodos para bloquear y desbloquear. Se conocen como acquire() y release() respectivamente. Ahora eche un vistazo al ejemplo a continuación.

Obtenga más información sobre Mutex aquí.

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
}

En el ejemplo anterior, creamos dos objetos Mutex con el nombre de mutex y mutex1. Usaremos mutex1 para controlar el cambio entre dos hilos. La razón para crear la Lista Vinculada es tener un historial de subprocesos. Ahora, agreguemos dos subprocesos en el código anterior. Dos hilos con el nombre de Productor y 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();
    }
  }
}

Explicación

El código anterior también se explica por sí mismo, pero esta explicación resolverá la confusión.

Dentro del hilo Productor

Cuando ejecute el programa anterior, creará un hilo de productor. Dentro de ese hilo, hay un bucle while que se ejecutará por tiempo indefinido. La cadena threadName es solo para mostrar la ejecución del hilo. El objeto mutex adquirirá el bloqueo para que el hilo consumidor sea funcional. (El objetivo principal de Mutex, obtener el control de la concurrencia).

Después de eso, el hilo productor se vuelve funcional. Entonces tenemos que lanzar este hilo para producción. En el hilo productor, liberaremos mutex1, el objeto responsable de manejar el cambio entre consumer y productor. Una vez liberado, los consumidores comenzarán a consumir, es decir, el hilo consumer será funcional.

Dentro del hilo del Consumer

Inmediatamente después de ingresar al hilo consumer, adquirimos mutex1 para detener la producción durante el consumo. Como puede ver, hemos creado tres consumidores con los nombres C1, C2 y C3. Para permitir que un consumidor sea funcional a la vez, también adquirimos mutex.

Después de eso, C1 se volverá funcional, mientras que se adquirirán C2 y C3. Una vez finalizado, mutex se liberará de nuevo, lo que permitirá que el otro consumidor sea funcional.

Así es como funciona mutex en Java. Después de ejecutar el programa anterior. Constantemente mostrará el número actual de hilos de productor que se están utilizando y el nombre del consumer que lo utiliza.

ejemplo de mutex de Java

El tamaño seguirá aumentando a medida que se ejecute el programa.

Autor: 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

Artículo relacionado - Java Threading