Limitaciones de la sincronización y los usos de la sincronización estática en subprocesos múltiples

La característica de subprocesos múltiples de Java es la característica en torno a la cual gira el concepto, ya que permite la ejecución simultánea de dos o más partes de un programa para la máxima utilización de la CPU. Cada parte de un programa de este tipo se denomina hilo. Entonces, los subprocesos son procesos livianos dentro de un proceso en el que, como todos sabemos, se pueden crear subprocesos mediante el uso de dos mecanismos que se enumeran:

  1. Extendiendo la clase Thread
  2. Implementación de la interfaz ejecutable

Si varios subprocesos acceden a un solo recurso a la vez, existe la posibilidad de que se produzcan carreras de datos o una mala salida. Entendamos esto con la ayuda de una historia. Tomemos el ejemplo de la carrera de datos en subprocesos múltiples para percibir las limitaciones de la sincronización y los usos de la sincronización estática. Comencemos directamente con la carrera de datos en subprocesos múltiples.

Implementación:

Shubham y Sharmistha estaban planeando una cita y trataron de reservar entradas para el cine. Desafortunadamente, solo 1 boleto estaba disponible. Shubham, que era un genio programador de Java, conocía un truco y solicitó 1 boleto simultáneamente para ambos al mismo tiempo. El ingenuo sistema de reserva de boletos asignó 2 subprocesos y los pasó a través del método del libro. Al final del procedimiento, ambos obtuvieron 1 boleto cada uno y el número de boletos restantes fue -1.

Ilustración: carreras de datos en subprocesos múltiples

Java

// Java program to show Data racing in multithreading.
 
// Helper class 1
class book {
    int tickets = 1;
    // method to book movie ticket
    void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println("No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating object "obj" of book class and passing
        // it to myThread class
        book obj = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
 
        // Starting threads created above
        t1.start();
        t2.start();
    }
}

Producción-

Shubham booked 1 ticket.
Sharmistha booked 1 ticket.
Tickets left: 0
Tickets left: -1

El número de boletos no puede ser negativo. Para manejar este problema, los ingenieros idearon el concepto de sincronización.

Sincronización: proporcionamos un bloqueo al objeto y declaramos un área sensible (método de retirada). Un objeto puede tener varios subprocesos, pero solo se puede acceder al área sensible mediante 1 subproceso a la vez.

Ilustración: manejo de carreras de datos debido a subprocesos múltiples mediante sincronización.

Java

// Java program to handle data racing due to
// multithreading using synchronization.
 
// Helper class 1
class book {
    int tickets = 1;
    // synchronized method to book movie ticket
    synchronized void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println("No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating object "obj" of book class and passing
        // it to myThread class
        book obj = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
 
        // Starting threads created above
        t1.start();
        t2.start();
    }
}

Producción-

Shubham booked 1 ticket.
Tickets left: 0
No tickets are available.

Limitaciones de sincronización:

Si tenemos múltiples subprocesos de 1 objeto, la sincronización manejará la carrera de datos o la mala salida. ¿Qué sucederá si se asignan varios subprocesos desde varios objetos? esto nuevamente resultará en una mala salida o carreras de datos.

Ilustración: Contras de la sincronización cuando se asignan varios subprocesos desde varios objetos.

Java

// Java program to illustrate limitations of
// synchronization.
 
// Helper class 1
class book {
    // tickets is static so all book objects have the same ticket count
    static int tickets = 1;
    // synchronized method to book movie ticket
    synchronized void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println("No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating multiple objects "obj" and "obj2" of
        // book class and passing it to myThread class.
        book obj = new book();
        book obj2 = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj2, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
 
        // Starting threads created above
        t1.start();
        t2.start();
    }
}

Producción-

Sharmistha booked 1 ticket.
Shubham booked 1 ticket.
Tickets left: 0
Tickets left: -1

¡Solo tenemos 1 boleto, pero debido a la carrera de datos, ambos se reservaron con éxito! Para manejar este problema necesitamos estudiar la sincronización estática.

Sincronización estática: digamos que tenemos 5 objetos. Cada objeto tiene múltiples hilos. ¡Ahora se accederá al área sensible por 5 subprocesos a la vez!

Para manejar este problema, a los ingenieros se les ocurrió la idea de la sincronización estática. Proporcionamos un bloqueo a la clase. La clase seleccionará 1 objeto a la vez. El objeto a su vez elegirá 1 hilo y lo pasará por el área sensible. 

Ilustración: Manejo de carreras de datos usando sincronización estática.

Java

// Java program to handle data racing using static
// synchronization.
 
// Helper class 1
class book {
    static int tickets = 1;
    // static synchronized method to book movie ticket
    static synchronized void book(int request, String name)
    {
        // logic to book ticket
        if (tickets >= request) {
            System.out.println(name + " booked " + request
                               + " ticket.");
            tickets = tickets - 1;
            System.out.println("Tickets left: " + tickets);
        }
        else {
            System.out.println(
                name + ", No tickets are available.");
        }
    }
}
// Helper class 2, extending Thread class.
// book method is called from this class using the object
// passed from main class.
class myThread extends Thread {
    book obj;
    int n;
    String name;
    myThread(book obj, String name, int n)
    {
        this.obj = obj;
        this.n = n;
        this.name = name;
    }
    // runs Threads
    public void run() { obj.book(n, name); }
}
// Driver class
public class GFG {
    // Driver method
    public static void main(String[] args)
    {
        // Creating object "obj" of book class and passing
        // it to myThread class
        book obj = new book();
        book obj2 = new book();
        myThread t1 = new myThread(obj, "Shubham", 1);
        myThread t2 = new myThread(obj2, "Sharmistha", 1);
        // When a program calls the start() method, a new
        // thread is created and then the run() method is
        // executed.
 
        // Starting threads created above
        t1.start();
        t2.start();
    }
}

Producción-

Shubham booked 1 ticket.
Tickets left: 0
Sharmistha, No tickets are available.

Usando sincronización estática, hemos preparado un sistema para evitar la reserva ilegal de boletos.

Conclusión-

  1. Cuando tenemos múltiples subprocesos de un solo objeto , podemos usar la sincronización para bloquear el objeto para pasar 1 subproceso a la vez y evitar una mala salida.
  2. Si se asignan múltiples subprocesos desde múltiples objetos , entonces no podemos usar la sincronización. En tales casos, proporcionar bloqueo al objeto dará como resultado una carrera de datos. necesitamos usar sincronización estática y proporcionar bloqueo a la clase. La clase seleccionará 1 objeto a la vez. El objeto a su vez elegirá 1 hilo y lo pasará al área sensible.

Publicación traducida automáticamente

Artículo escrito por dattabikash505 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *