viernes, 9 de junio de 2017

Importancia del uso de Synchronized al implementar Threads (Hilos) en Java

Un bloque o método sincronizado en Java es aquel que utiliza la palabra reservada synchronized.

La importancia en su uso radica en evitar o prevenir las condiciones de carrera(race condition) al manejar hilos en Java.

La palabra reservada Synchronized.

Los bloques sincronizados en Java están marcados con la palabra clave synchronized. Un bloque sincronizado en Java se sincroniza en algún objeto. Todos los bloques synchronized sincronizados en el mismo objeto sólo pueden tener un subproceso ejecutándose dentro de ellos al mismo tiempo. 

Todos los demás hilos que intentan entrar en el bloque sincronizado se bloquean hasta que el hilo dentro del bloque sincronizado sale.

La palabra reservada synchronized puede utilizarse para cuatro tipos de bloques diferentes:
Metodos de instancia, metodos estáticos, bloques de código dentro de metodos de instancia, bloques de código dentro de metodos estáticos. 

El tipo de bloque synchronized que necesites dependerá de una situación concreta.

Ejemplo.


He aquí un ejemplo que inicia 2 subprocesos y que ambos llaman al método agregar en la misma instancia de Cobro. Sólo un hilo a la vez podrá llamar al método agregar en la misma instancia, ya que el método se sincroniza en la instancia a la que pertenece.

public class Cobro{
     
     long contar = 0;
    
     public synchronized void agregar(long valor){
       this.contar += valor;
     }
  }

public class CobroThread extends Thread{

     protected Cobro cobro = null;

     public CobroThread(Cobro cobro){
        this.cobro = cobro;
     }

     public void run() {
 for(int i=0; i<10; i++){
           cobro.agregar(i);
        }
     }
  }

  public class Ejemplo {

    public static void main(String[] args){
      Cobro cobro = new Cobro();
      Thread  threadA = new CobroThread(cobro);
      Thread  threadB = new CobroThread(cobro);

      threadA.start();
      threadB.start(); 
    }
  }

Se crean dos subprocesos. La misma instancia de cobro se pasa a ambos en su constructor. El método agregar() se sincroniza en la instancia, porque el método agregar es un método de instancia y se marca como sincronizado. Por lo tanto, sólo uno de los subprocesos puede llamar al método agregar() a la vez. El otro hilo esperará hasta que el primer hilo deje el método agregar(), antes de que pueda ejecutar el método mismo.

Si los dos subprocesos hubieran hecho referencia a dos instancias de cobro distintas, no habría problemas para llamar a los métodos agregar() simultáneamente. Las llamadas habrían sido a objetos diferentes, por lo que los métodos llamados también estarían sincronizados en diferentes objetos (el objeto que posee el método). Por lo tanto las llamadas no bloquearían. Aquí es cómo podría verse:

 public class Ejemplo {

    public static void main(String[] args){
      Cobro cobroA = new Cobro();
      Cobro cobroB = new Cobro();
      Thread  threadA = new CobroThread(cobroA);
      Thread  threadB = new CobroThread(cobroB);

      threadA.start();
      threadB.start(); 
    }
  }

 Observe cómo los dos subprocesos, threadA y threadB, ya no hacen referencia a la misma instancia de cobro. El método agregar de cobroA y cobroB se sincroniza en sus dos instancias propietarias. Llamar agregar() en cobroA no bloqueará así una llamada a agregar() en cobroB.

A modo de ejemplos de alto nivel si no usáramos synchronized cuando manipulamos hilos podría darse el caso que multiples hilos alteren el estado o las características de un mismo objeto causando problemas como los siguientes

Un sistema mal diseñado de reserva de entradas podría ocasionar que dos usuarios accediendo desde la web a la vez, reserven legítimamente la misma butaca. O un sistema de conteo automático de plazas libres de un parking en sus barreras de entrada y salida de vehículos podría indicar que está totalmente vacío cuando realmente está lleno (o viceversa). De igual forma, dos personas ingresando y retirando efectivo a la vez de una misma cuenta bancaria podrían ver su saldo incrementado o por el contrario su ingreso realizado pero no materializado en saldo disponible. Si bien son situaciones que pudieran ser improbables, son posibles y pueden ser y han de ser evitadas en el desarrollo de software.

Si los procesos que están en condición de carrera (race condition) son correctamente sincronizados, todo debería funcionar correctamente, por lo que el resultado será el esperado. Múltiples procesos se encuentran en condición de carrera si el resultado de los mismos depende del orden de su llegada y si no son correctamente sincronizados, puede producirse una corrupción de datos, que puede derivar incluso en un problema de seguridad del sistema capaz de ser explotado de forma malintencionada. Análogamente, en circuitos electrónicos se da una condición de carrera cuando la salida de un sistema o subsistema depende del orden en que se hayan mandado las solicitudes de activación o desactivación de sus componentes.


Recuerda que este blog sobrevive gracias a tus donaciones o clics en los anuncios, ya sabes como apoyar este recurso para continuar subiendo mas tutoriales. Gracias.























1 comentario:

  1. Casinos Near Casinos in Las Vegas, NV - MapYRO
    Looking for Casinos Near 서귀포 출장마사지 Casinos near me? 당진 출장마사지 Find 9 Casinos Near Me found here. 광주 출장샵 MapYRO is 부산광역 출장안마 a trusted source for the best casino information and reviews 시흥 출장샵 in Las Vegas, NV.

    ResponderEliminar