Diferencia entre atómico, volátil y sincronizado en Java

Synchronized es el modificador aplicable solo para métodos y bloques pero no para las variables y clases. Puede haber una posibilidad de un problema de inconsistencia de datos para superar este problema, debemos optar por una palabra clave sincronizada cuando varios subprocesos intentan operar simultáneamente en el mismo objeto Java. Si un método o bloque se declara sincronizado, solo un subproceso a la vez puede ejecutar ese método o bloque en el objeto dado para que se resuelva el problema de inconsistencia de datos. La principal ventaja de las palabras clave sincronizadas es que podemos resolver problemas de inconsistencia de datos, pero la principal desventaja de esta palabra clave es que aumenta el tiempo de espera del hilo y crea problemas de rendimiento. Por lo tanto, no se recomienda usar la palabra clave sincronizada cuando no hay un requisito específico. Cada objeto en Java tiene un bloqueo único. El concepto de candado entrará en escena cuando estemos usando una palabra clave sincronizada. 

Los subprocesos restantes no pueden ejecutar ningún método sincronizado simultáneamente en el mismo objeto cuando un subproceso ejecuta un método sincronizado en el objeto dado. Pero los subprocesos restantes pueden ejecutar el método no sincronizado simultáneamente.

Modificador volátil:

Si el valor de una variable sigue cambiando por varios subprocesos, es posible que haya un problema de inconsistencia de datos. Es un modificador aplicable solo para variables, y no podemos aplicarlo en ningún otro lugar. Podemos resolver este problema usando un modificador volátil. Si una variable se declara tan volátil como para cada subproceso JVMcreará una copia local separada. Cada modificación realizada por el hilo se llevará a cabo en la copia local para que no tenga efecto en los hilos restantes. Superar el problema de inconsistencia de datos es la ventaja y la palabra clave volátil es crear y mantener una copia separada para cada subproceso aumenta la complejidad de la programación y crea un problema de rendimiento es una desventaja. Por lo tanto, si no hay requisitos específicos, nunca se recomienda utilizar palabras clave volátiles.

Modificador atómico:  

Si el valor de una variable sigue cambiando por múltiples subprocesos, entonces puede haber una posibilidad de un problema de inconsistencia de datos. Podemos resolver este problema usando una variable atómica. El problema de inconsistencia de datos se puede resolver cuando los objetos de estas clases representan la variable atómica de referencia int, long, boolean y object respectivamente.

Ejemplo:

En el siguiente ejemplo, cada subproceso incrementa la variable de conteo 5 veces. Entonces, después de la ejecución de dos subprocesos, el valor de la cuenta final debe ser 10.

Java

// import required packages
import java.io.*;
import java.util.*;
 
// creating a thread by extending a thread class
class myThread extends Thread {
   
    // declaring a count variable
    private int count;
 
    public void run()
    {
        // calculating the count
        for (int i = 1; i <= 5; i++) {
 
            try {
                Thread.sleep(i * 100);
                count++;
            }
            catch (InterruptedException
                       e) { // throwing an exception
                System.out.println(e);
            }
        }
    }
    // returning the count value
    public int getCount() { return this.count; }
}
// driver class
public class GFG {
   
    // main method
    public static void main(String[] args)
        throws InterruptedException
    {
 
        // creating an thread object
        myThread t = new myThread();
        Thread t1 = new Thread(t, "t1");
       
        // starting thread t1
        t1.start();
        Thread t2 = new Thread(t, "t2");
       
        // starting thread t2
        t2.start();
       
        // calling join method on thread t1
        t1.join();
       
        // calling join method on thread t1
        t2.join();
       
        // displaying the count
        System.out.println("count=" + t.getCount());
    }
}
Producción

count=10

Si ejecutamos el programa anterior, notaremos que el valor de conteo varía entre 6,7,8.9 La razón es que conteo++ no es una operación atómica. Entonces, cuando un subproceso lee su valor y lo incrementa en uno, otro subproceso ha leído el valor anterior, lo que lleva a un resultado incorrecto. Para resolver este problema, tendremos que asegurarnos de que la operación de incremento en la cuenta sea atómica.

El siguiente programa siempre generará un valor de conteo como 8 porque el método AtomicInteger incrementAndGet() incrementa atómicamente el valor actual en uno. 

Java

// import required packages
import java.io.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
 
// creating a thread by extending a thread class
class myThread extends Thread {
   
    // declaring an atomic variable
    private AtomicInteger count = new AtomicInteger();
 
    public void run()
    {
        // calculating the count
        for (int i = 1; i <= 5; i++) {
            try {
               
                // putting  thread on sleep
                Thread.sleep(i * 100);
               
                // calling incrementAndGet() method
                // on count variable
                count.incrementAndGet();
            }
            catch (InterruptedException e) {
               
                // throwing exception
                System.out.println(e);
            }
        }
    }
    // returning the count value
    public AtomicInteger getCount() { return count; }
}
// driver class
public class GFG {
   
    // main method
    public static void main(String[] args)
        throws InterruptedException
    {
        // creating an thread object
        myThread t = new myThread();
       
        Thread t1 = new Thread(t, "t1");
       
        // starting thread t1
        t1.start();
       
        Thread t2 = new Thread(t, "t2");
       
        // starting thread t2
        t2.start();
       
        // calling join method on thread t1
        t1.join();
       
        // calling join method on thread t1
        t2.join();
       
        // displaying the count
        System.out.println("count=" + t.getCount());
    }
}
Producción

count=10
                     sincronizado                       Volátil                  Atómico
1. Es aplicable solo a bloques o métodos. 1. Es aplicable solo a variables. 1. También es aplicable solo a variables.
2. El modificador sincronizado se usa para implementar un algoritmo concurrente basado en bloqueo, y es decir, sufre la limitación del bloqueo. 2.Mientras que Volatile da el poder de implementar un algoritmo sin bloqueo que es más escalable. 2. Atomic también da el poder de implementar el algoritmo de no bloqueo.
3. El rendimiento es relativamente bajo en comparación con las palabras clave volátiles y atómicas debido a la adquisición y liberación del bloqueo. 3. El rendimiento es relativamente alto en comparación con la palabra clave sincronizada. 3. El rendimiento es relativamente alto en comparación con las palabras clave volátiles y sincronizadas.
4. Debido a su naturaleza de bloqueo, no es inmune a los peligros de concurrencia, como interbloqueo y bloqueo dinámico. 4. Debido a su naturaleza sin bloqueo, es inmune a los peligros de concurrencia, como interbloqueos y bloqueos dinámicos. 4. Debido a su naturaleza sin bloqueo, es inmune a los peligros de concurrencia, como interbloqueos y bloqueos dinámicos.

Publicación traducida automáticamente

Artículo escrito por mroshanmishra0072 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 *