La sincronización en Java es la capacidad de controlar el acceso de múltiples subprocesos a cualquier recurso compartido.
La sincronización de Java es una mejor opción cuando queremos permitir que solo un hilo acceda al recurso compartido.
¿Por qué utilizar la sincronización?
La sincronización se utiliza principalmente para
- Para evitar interferencias con el hilo.
- Para evitar problemas de consistencia.
Tipos de sincronización
Hay dos tipos de sincronización.
- Sincronización de procesos
- Sincronización de hilos
Aquí, discutiremos solo la sincronización de subprocesos.
Sincronización de hilos
Hay dos tipos de sincronización de subprocesos, comunicación mutuamente excluyente y entre subprocesos.
- Exclusivo mutuo
- Método sincronizado.
- Bloque sincronizado.
- Sincronización estática.
- Cooperación (comunicación entre subprocesos en Java)
Exclusivo mutuo
Mutual Exclusive ayuda a evitar que los hilos interfieran entre sí mientras comparten datos. Se puede lograr mediante el uso de las siguientes tres formas:
- Utilizando el método sincronizado
- Mediante el uso de bloque sincronizado
- Mediante el uso de sincronización estática
Concepto de bloqueo en Java
La sincronización se basa en una entidad interna conocida como bloqueo o monitor. Cada objeto tiene un candado asociado. Por convención, un hilo que necesita acceso consistente a los campos de un objeto tiene que adquirir el bloqueo del objeto antes de acceder a ellos, y luego liberar el bloqueo cuando haya terminado con ellos.
Desde Java 5, el paquete java.util.concurrent.locks contiene varias implementaciones de bloqueo.
Comprender el problema sin sincronización
En este ejemplo, no hay sincronización, por lo que la salida es inconsistente. Veamos el ejemplo:
TestSynchronization1.java
class Table{ void printTable(int n){//method not synchronized for(int i=1;i<=5;i++){ system.out.println(n*i); try{ thread.sleep(400); }catch(exception e){system.out.println(e);} } class mythread1 extends thread{ table t; mythread1(table t){ this.t="t;" public void run(){ t.printtable(5); mythread2 mythread2(table t.printtable(100); testsynchronization1{ static main(string args[]){ obj="new" table(); only one object t1="new" mythread1(obj); t2="new" mythread2(obj); t1.start(); t2.start(); < pre> <p> <strong>Output:</strong> </p> <pre> 5 100 10 200 15 300 20 400 25 500 </pre> <h3>Java Synchronized Method</h3> <p>If you declare any method as synchronized, it is known as synchronized method.</p> <p>Synchronized method is used to lock an object for any shared resource.</p> <p>When a thread invokes a synchronized method, it automatically acquires the lock for that object and releases it when the thread completes its task.</p> <p> <strong>TestSynchronization2.java</strong> </p> <pre> //example of java synchronized method class Table{ synchronized void printTable(int n){//synchronized method for(int i=1;i<=5;i++){ system.out.println(n*i); try{ thread.sleep(400); }catch(exception e){system.out.println(e);} } class mythread1 extends thread{ table t; mythread1(table t){ this.t="t;" public void run(){ t.printtable(5); mythread2 mythread2(table t.printtable(100); testsynchronization2{ static main(string args[]){ obj="new" table(); only one object t1="new" mythread1(obj); t2="new" mythread2(obj); t1.start(); t2.start(); < pre> <p> <strong>Output:</strong> </p> <pre> 5 10 15 20 25 100 200 300 400 500 </pre> <h3>Example of synchronized method by using annonymous class</h3> <p>In this program, we have created the two threads by using the anonymous class, so less coding is required.</p> <p> <strong>TestSynchronization3.java</strong> </p> <pre> //Program of synchronized method by using annonymous class class Table{ synchronized void printTable(int n){//synchronized method for(int i=1;i<=5;i++){ system.out.println(n*i); try{ thread.sleep(400); }catch(exception e){system.out.println(e);} } public class testsynchronization3{ static void main(string args[]){ final table obj="new" table(); only one object thread t1="new" thread(){ run(){ obj.printtable(5); }; t2="new" obj.printtable(100); t1.start(); t2.start(); < pre> <p> <strong>Output:</strong> </p> <pre> 5 10 15 20 25 100 200 300 400 500 </pre> <hr></=5;i++){></pre></=5;i++){></pre></=5;i++){>
Método sincronizado de Java
Si declara algún método como sincronizado, se lo conoce como método sincronizado.
El método sincronizado se utiliza para bloquear un objeto para cualquier recurso compartido.
Cuando un hilo invoca un método sincronizado, automáticamente adquiere el bloqueo para ese objeto y lo libera cuando el hilo completa su tarea.
TestSynchronization2.java
//example of java synchronized method class Table{ synchronized void printTable(int n){//synchronized method for(int i=1;i<=5;i++){ system.out.println(n*i); try{ thread.sleep(400); }catch(exception e){system.out.println(e);} } class mythread1 extends thread{ table t; mythread1(table t){ this.t="t;" public void run(){ t.printtable(5); mythread2 mythread2(table t.printtable(100); testsynchronization2{ static main(string args[]){ obj="new" table(); only one object t1="new" mythread1(obj); t2="new" mythread2(obj); t1.start(); t2.start(); < pre> <p> <strong>Output:</strong> </p> <pre> 5 10 15 20 25 100 200 300 400 500 </pre> <h3>Example of synchronized method by using annonymous class</h3> <p>In this program, we have created the two threads by using the anonymous class, so less coding is required.</p> <p> <strong>TestSynchronization3.java</strong> </p> <pre> //Program of synchronized method by using annonymous class class Table{ synchronized void printTable(int n){//synchronized method for(int i=1;i<=5;i++){ system.out.println(n*i); try{ thread.sleep(400); }catch(exception e){system.out.println(e);} } public class testsynchronization3{ static void main(string args[]){ final table obj="new" table(); only one object thread t1="new" thread(){ run(){ obj.printtable(5); }; t2="new" obj.printtable(100); t1.start(); t2.start(); < pre> <p> <strong>Output:</strong> </p> <pre> 5 10 15 20 25 100 200 300 400 500 </pre> <hr></=5;i++){></pre></=5;i++){>
Ejemplo de método sincronizado mediante el uso de una clase anónima
En este programa, hemos creado los dos subprocesos utilizando la clase anónima, por lo que se requiere menos codificación.
TestSynchronization3.java
//Program of synchronized method by using annonymous class class Table{ synchronized void printTable(int n){//synchronized method for(int i=1;i<=5;i++){ system.out.println(n*i); try{ thread.sleep(400); }catch(exception e){system.out.println(e);} } public class testsynchronization3{ static void main(string args[]){ final table obj="new" table(); only one object thread t1="new" thread(){ run(){ obj.printtable(5); }; t2="new" obj.printtable(100); t1.start(); t2.start(); < pre> <p> <strong>Output:</strong> </p> <pre> 5 10 15 20 25 100 200 300 400 500 </pre> <hr></=5;i++){>
=5;i++){>=5;i++){>=5;i++){>