Thread Safety y cómo lograrlo en Java

Como sabemos, Java tiene una característica, Multithreading , que es un proceso de ejecución de múltiples hilos simultáneamente. Cuando varios subprocesos están trabajando en los mismos datos y el valor de nuestros datos está cambiando, ese escenario no es seguro para subprocesos y obtendremos resultados inconsistentes. Cuando un subproceso ya está trabajando en un objeto y evita que otro subproceso trabaje en el mismo objeto, este proceso se denomina seguridad de subprocesos. 

Cómo lograr la seguridad de subprocesos

Hay cuatro formas de lograr Thread Safety en Java . Estos son:

  1. Uso de la sincronización .
  2. Uso de palabras clave volátiles .
  3. Uso de la variable atómica .
  4. Uso de la palabra clave final .

Uso de sincronización

La sincronización es el proceso de permitir que solo un subproceso a la vez complete la tarea en particular. Significa que cuando varios subprocesos se ejecutan simultáneamente y desean acceder al mismo recurso al mismo tiempo, se producirá el problema de la incoherencia. por lo tanto, la sincronización se usa para resolver el problema de inconsistencia al permitir solo un hilo a la vez. 
La sincronización utiliza una palabra clave sincronizada . Sincronizado es el modificador que crea un bloque de código conocido como sección crítica. 
 

Java

class A {
    synchronized void sum(int n)
    {
 
        // Creating a thread instance
        Thread t = Thread.currentThread();
        for (int i = 1; i <= 5; i++) {
            System.out.println(
                t.getName() + " : " + (n + i));
        }
    }
}
 
// Class B extending thread class
class B extends Thread {
 
    // Creating an object of class A
    A a = new A();
    public void run()
    {
 
        // Calling sum() method
        a.sum(10);
    }
}
class Test {
    public static void main(String[] args)
    {
 
        // Creating an object of class B
        B b = new B();
 
        // Initializing instance t1 of Thread
        // class with object of class B
        Thread t1 = new Thread(b);
 
        // Initializing instance t2 of Thread
        // class with object of class B
        Thread t2 = new Thread(b);
 
        // Initializing thread t1 with name
        //'Thread A'
        t1.setName("Thread A");
 
        // Initializing thread t2 with name
        //'Thread B'
        t2.setName("Thread B");
 
        // Starting thread instance t1 and t2
        t1.start();
        t2.start();
    }
}
Producción: 

Thread A : 11
Thread A : 12
Thread A : 13
Thread A : 14
Thread A : 15
Thread B : 11
Thread B : 12
Thread B : 13
Thread B : 14
Thread B : 15

 

Usando la palabra clave volátil

Una palabra clave volátil es un modificador de campo que garantiza que el objeto pueda ser utilizado por múltiples subprocesos al mismo tiempo sin tener ningún problema. volatile es una buena manera de garantizar que el programa Java sea seguro para subprocesos. una palabra clave volátil se puede usar como una forma alternativa de lograr Thread Safety en Java.
 

Java

public class VolatileExample {
 
    // Initializing volatile variables
    // a, b
    static volatile int a = 0, b = 0;
 
    // Defining a static void method
    static void method_one()
    {
        a++;
        b++;
    }
 
    // Defining static void method
    static void method_two()
    {
        System.out.println(
            "a=" + a + " b=" + b);
    }
 
    public static void main(String[] args)
    {
 
        // Creating an instance t1 of
        // Thread class
        Thread t1 = new Thread() {
            public void run()
            {
                for (int i = 0; i < 5; i++)
                    method_one();
            }
        };
 
        // Creating an instance t2 of
        // Thread class
        Thread t2 = new Thread() {
            public void run()
            {
                for (int i = 0; i < 5; i++)
                    method_two();
            }
        };
 
        // Starting instance t1 and t2
        t1.start();
        t2.start();
    }
}
Producción: 

a=5 b=5
a=5 b=5
a=5 b=5
a=5 b=5
a=5 b=5

 

Usando variable atómica

El uso de una variable atómica es otra forma de lograr la seguridad de subprocesos en Java. Cuando las variables son compartidas por varios subprocesos, la variable atómica garantiza que los subprocesos no choquen entre sí. 
 

Java

import java.util.concurrent.atomic.AtomicInteger;
 
class Counter {
 
    // Creating a variable of
    // class type AtomicInteger
    AtomicInteger count
        = new AtomicInteger();
 
    // Defining increment() method
    // to change value of
    // AtomicInteger variable
    public void increment()
    {
        count.incrementAndGet();
    }
}
 
public class TestCounter {
    public static void main(
        String[] args) throws Exception
    {
 
        // Creating an instance of
        // Counter class
        Counter c = new Counter();
 
        // Creating an instance t1 of
        // Thread class
        Thread t1 = new Thread(
            new Runnable() {
                public void run()
                {
                    for (int i = 1; i <= 2000; i++) {
                        c.increment();
                    }
                }
            });
 
        // Creating an instance t2
        // of Thread class
        Thread t2 = new Thread(
            new Runnable() {
                public void run()
                {
                    for (int i = 1; i <= 2000; i++) {
                        c.increment();
                    }
                }
            });
 
        // Calling start() method with t1 and t2
        t1.start();
        t2.start();
 
        // Calling join method with t1 and t2
        t1.join();
        t2.join();
 
        System.out.println(c.count);
    }
}
Producción: 

4000

 

Uso de la palabra clave Final 

Las variables finales también son seguras para subprocesos en Java porque una vez asignada alguna referencia de un objeto, no puede apuntar a la referencia de otro objeto. 
 

Java

public class FinalTest {
 
    // Initializing a string
    // variable of final type
    final String str
        = new String("hello");
 
    // Defining a method to
    // change the value of the final
    // variable which is not possible,
    // hence the error will be shown
    void method()
    {
        str = "world";
    }
}

Producción:

Compilation Error in java code :- 
prog.java:14: error: cannot assign a value to final variable str
        str = "world";
        ^
1 error

Publicación traducida automáticamente

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