Synccronización en Java
¿Qué es Synccronización en Java?
In JavaLa sincronización se refiere a la capacidad de controlar el acceso de varios subprocesos a cualquier recurso compartido. Es una opción ideal cuando queremos permitir que solo un subproceso acceda al recurso compartido.
Este enfoque de ejecución suele denominarse programación "asincrónica". En estos procesadores también hay subprocesos, que son procesos ligeros que pueden ejecutar instrucciones simultáneamente.
Tipos de Synchronización
Hay dos tipos de métodos de sincronización en Java:
1) Sincronización de procesos
2) Sincronización de hilos.
Estudiemos Thread y Sincronización de procesos en detalle.
Sincronización de procesos: Gestiona la sincronización entre programas. Por ejemplo, programas como `Microsoft Word` y `Acrobat Reader` se ejecutan como procesos individuales.
Sincronización de hilos: La ejecución simultánea del recurso crítico por dos o más subprocesos se denomina subproceso. Synccronización. Puede agruparse aún más en comunicación mutuamente excluyente y entre subprocesos.
¿Qué es el bloqueo? Java?
Cerrar Java Se construye alrededor de una entidad interna conocida como monitor o cerradura. Todos los objetos tienen un candado asociado. Por lo tanto, el hilo que necesita acceso consistente a los campos de un objeto debe adquirir el bloqueo del objeto antes de acceder a ellos, y libera el bloqueo cuando finaliza el trabajo. Esto garantiza que solo un hilo acceda a los datos compartidos a la vez.
Programa multiproceso con sincronización
Un programa multiproceso es un método o bloque protegido de la interferencia de otros hilos que comparten el mismo recurso indicado mediante la palabra clave `synchronized`.
Utilizando el método sincronizado
Cualquier método que se declara como sincronizado se conoce como método sincronizado. También se utiliza para bloquear un objeto para cualquier recurso compartido. Por lo tanto, cuando un hilo invoca un método sincronizado, toma posesión automáticamente del bloqueo de ese objeto y lo libera cuando ha finalizado su tarea.
Nota: La palabra clave sincronizada no puede funcionar con clases y variables. Solo se pueden usar métodos y bloques con la palabra clave.
¿Por qué utilizar el Sync¿Método armonizado?
- Se utiliza para bloquear un objeto para cualquier recurso compartido.
- El objeto obtiene el bloqueo cada vez que se llama al método sincronizado.
- El bloqueo no se libera hasta que el hilo completa su función.
Sintaxis:
Acess_modifiers synchronized return_type method_name (Method_Parameters) { }
class MathService { synchronized void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); } }
Explicación del código:
Ejecute este ejemplo y observe que el subproceso `0` obtiene primero el bloqueo del objeto `mathService` y usa este bloqueo exclusivamente hasta que haya completado la ejecución. Los subprocesos `0` y `1` no están entrelazados en este código. El resultado es el que se muestra a continuación.
Salida:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Usando un bloque sincronizado
Supongamos que no desea sincronizar todo el método, sino que desea sincronizar algunas líneas de código. En ese momento, SyncEl bloque sincronizado ayudó a sincronizar el seleccionado. Java código. SyncA los bloqueos de métodos sincronizados se accede en el método, mientras que a los bloqueos de bloques sincronizados se accede en el objeto.
class MathService { void getSumOfArray(int[] numbers) { synchronized (this){ int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); } }
Explicación del código:
Al ejecutar este código, notará que funciona sin ninguna interferencia. En el método sincronizado, el bloqueo lo aplica el método, pero en el bloque sincronizado, el bloqueo lo aplica el objeto. Asegúrese de que el resultado sea como se muestra a continuación.
Salida:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Explicación del código:
Cuando ejecutes este código, notarás que funciona sin interferencias, que es lo que esperábamos. En el método sincronizado, el bloqueo lo aplica el método, pero en el método de bloque sincronizado, el bloqueo lo aplica el objeto.
Usando sincronización estática
In Java Sincronización: si hay más de un objeto, dos subprocesos pueden adquirir los bloqueos y entrar en un bloque o bloques sincronizados, con un bloqueo independiente para cada objeto. Para evitar esto, se puede utilizar la sincronización estática. SyncLas palabras clave sincronizadas se utilizarán antes que los métodos estáticos.
Nota: En la sincronización estática, el acceso de bloqueo está en la clase, no en el objeto y el método.
Código para demostrar el problema del bloqueo de múltiples objetos
class MathService { synchronized void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); MathService mathService1 = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); Thread threadThree = new Thread(() -> mathService1.getSumOfArray(new int[]{10, 11, 12})); Thread threadFour = new Thread(() -> mathService1.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); threadThree.start(); threadFour.start(); } }
Explicación del código:
Cuando creamos otra instancia de `MathService`, introducimos interferencia en los hilos, ya que se entrelazarán con los dos objetos. Tenga en cuenta que el hilo `0` y el hilo `2` están intercalados con los dos objetos, mientras que los hilos `1` y `3` están intercalados con los dos objetos.
Salida:
Thread-0 adds 0 to 10 to get -> 10 Thread-2 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-2 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-2 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-3 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-3 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63 Thread-3 adds 41 to 22 to get -> 63
El mismo código usando el método estático sincronizado
class MathService { synchronized static void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); MathService mathService1 = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); Thread threadThree = new Thread(() -> mathService1.getSumOfArray(new int[]{10, 11, 12})); Thread threadFour = new Thread(() -> mathService1.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); threadThree.start(); threadFour.start(); } }
Ejecute el código anterior y observe que ahora hemos eliminado la interferencia de subprocesos. La salida del código se muestra a continuación.
Salida:
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-3 adds 0 to 20 to get -> 20 Thread-3 adds 20 to 21 to get -> 41 Thread-3 adds 41 to 22 to get -> 63 Thread-2 adds 0 to 10 to get -> 10 Thread-2 adds 10 to 11 to get -> 21 Thread-2 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Ventajas de utilizar la sincronización
Estas son las ventajas de trabajar con aplicaciones concurrentes:
- El objetivo principal de la sincronización en Java es para evitar datos inconsistentes al evitar la interferencia de subprocesos.
- La palabra clave sincronizada en Java Proporciona bloqueo, lo que garantiza el acceso mutuamente exclusivo al recurso compartido y evita la carrera de datos.
- También evita el reordenamiento de declaraciones de código por parte del compilador, lo que puede causar un problema concurrente sutil si no usamos palabras clave volátiles o sincronizadas.
- SyncLa palabra clave ronizada lee datos de la memoria principal que del caché y cuando libera el bloqueo.
- También limpia las operaciones de escritura de la memoria principal, eliminando errores de inconsistencia de memoria.
Desventajas de SyncMecanismo de cronización
SyncLos mecanismos de cronización tienen un desempeño deficiente.
Por ejemplo:
- Suponga que hay cinco procesos, A1, A2, A3, A4 y A5.
- Están esperando que los recursos compartidos accedan a un hilo a la vez.
- Todos los procesos se mantienen en espera, por lo que el último de la cola debe esperar hasta que se completen todos los demás procesos.
Resumen
- SyncLa cronización se refiere a la capacidad de controlar el acceso de múltiples subprocesos a cualquier recurso compartido.
- Java tiene dos tipos de métodos de sincronización: 1) Sincronización de procesos y 2) Sincronización de hilos.
- Cerrar Java Se construye alrededor de una entidad interna conocida como monitor o cerradura.
- Un programa multiproceso es un método o bloque protegido de la interferencia de otros subprocesos que comparten el mismo recurso indicado mediante la palabra clave `synchronized`.
- Cualquier método que se declara como sincronizado se conoce como método sincronizado.
- In JavaA los bloqueos de métodos sincronizados se accede en el método, mientras que a los bloqueos de bloques sincronizados se accede en el objeto.
- En la sincronización estática, el acceso de bloqueo está en la clase, no en el objeto y el método.
- El objetivo principal de la sincronización en Java es para evitar datos inconsistentes al evitar la interferencia de subprocesos.
- El mayor inconveniente de este método es que todos los procesos se mantienen en espera, por lo que el último de la cola debe esperar hasta que se completen todos los demás procesos.