La palabra clave sincronizada representa que este método está bloqueado. Es equivalente a no importa qué hilo (como el hilo A), al ejecutar este método, debe verificar si otros hilos B (o C, D, etc.) están utilizando este método (u otros métodos de sincronización de esta clase). Si es así, espere el hilo B (o C, D) que está utilizando el método sincronizado para ejecutar este método antes de ejecutar este método. Si no, bloquea la persona que llama y ejecútelo directamente. Incluye dos usos: el método sincronizado y el bloque sincronizado.
El mecanismo de sincronización de múltiples subprocesos bloquea los recursos para que al mismo tiempo, solo un hilo pueda operar, y la sincronización se utiliza para resolver los problemas que pueden surgir cuando múltiples hilos acceden simultáneamente.
El mecanismo de sincronización se puede implementar utilizando la palabra clave sincronizada.
Cuando la palabra clave sincronizada modifica un método, el método se llama método de sincronización.
Cuando se ejecuta el método sincronizado o se produce una excepción, el bloqueo se lanzará automáticamente.
El siguiente es un ejemplo para analizar el uso de palabras clave sincronizadas.
1. Uso diferencial de palabras clave sincronizadas
Programa de ejemplo 1
public class Threadtest {public static void main (string [] args) {ejemplo ejemplo = new Ejemplo (); Thread t1 = new Thread1 (ejemplo); Thread t2 = new Thread1 (ejemplo); t1.start (); t2.start (); }} Ejemplo de clase {public sincronizado void ejecutute () {for (int i = 0; i <10; ++ i) {try {thread.sleep (500); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("Hola:" + i); }}} La clase Thread1 extiende el hilo {ejemplo privado de ejemplo; public Thread1 (ejemplo de ejemplo) {this.example = ejemplo; } @Override public void run () {ejemplo.ExeCute (); }} Si se debe prever la palabra clave sincronizada en el método Execute (), los resultados de ejecución de este programa de ejemplo serán muy diferentes.
Si no se agrega la palabra clave sincronizada, los dos subprocesos ejecutan el método Execute () al mismo tiempo, y la salida es dos grupos de concurrentes.
Si se agrega la palabra clave sincronizada, primero se emitirá un conjunto de 0 a 9, y luego se emitirá el siguiente conjunto, lo que indica que los dos subprocesos se ejecutan en secuencia.
2. Situación múltiple de múltiples métodos
Cambie el programa y agregue otro método Execute2 () a la clase de ejemplo.
Luego escriba una clase de hilo Thread2. El método run () en Thread2 ejecuta Execute2 (). Ambos métodos en la clase de ejemplo se modifican mediante la palabra clave sincronizada.
Programa de ejemplo 2
public class Threadtest {public static void main (string [] args) {ejemplo ejemplo = new Ejemplo (); Thread t1 = new Thread1 (ejemplo); Thread t2 = new Thread2 (ejemplo); t1.start (); t2.start (); }} Ejemplo de clase {public sincronizado void ejecute () {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("Hola:" + i); }} public sincronizado void ejecutute2 () {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("World:" + i); }}} La clase Thread1 extiende el hilo {ejemplo privado de ejemplo; public Thread1 (ejemplo de ejemplo) {this.example = ejemplo; } @Override public void run () {ejemplo.ExeCute (); }} La clase Thread2 extiende el hilo {ejemplo privado de ejemplo; public Thread2 (ejemplo de ejemplo) {this.example = ejemplo; } @Override public void run () {ejemplo.Execute2 (); }} Si se elimina la palabra clave sincronizada, los dos métodos se ejecutan simultáneamente y no tienen influencia mutua.
Pero como se escribe en la subrutina de ejemplo, incluso dos métodos:
El resultado de la ejecución siempre es la salida de un hilo y luego la ejecución de otro hilo.
ilustrar:
Si un objeto tiene múltiples métodos sincronizados, y un hilo ha entrado en un método sincronizado en un momento determinado, entonces otros subprocesos no pueden acceder a ningún método sincronizado del objeto antes de ejecutar el método.
en conclusión:
Cuando la palabra clave sincronizada modifica un método, el método se llama método de sincronización.
Cada objeto en Java tiene un bloqueo o un monitor. Cuando un hilo accede al método sincronizado de un objeto, el objeto está bloqueado y ningún otro hilo puede acceder al método sincronizado del objeto (aquí se refiere a todos los métodos de sincronización, no solo el mismo método). No es hasta que el hilo anterior completa el método de ejecución (o lanza una excepción), se libera el bloqueo del objeto, para que otros subprocesos puedan acceder al método sincronizado del objeto nuevamente.
Tenga en cuenta que el objeto está bloqueado en este momento. Si se trata de un objeto diferente, no hay una relación de restricción entre los objetos.
Al intentar construir un segundo objeto de hilo en el código, se pasa un nuevo objeto de ejemplo, entonces no hay restricción entre la ejecución de los dos hilos.
3. Considere los métodos de sincronización estática
Cuando Static también modifica un método de palabra clave sincronizado, se ha dicho antes que un método de sincronización no estático bloqueará el objeto, pero el método estático no pertenece al objeto, sino a una clase, y bloqueará el objeto de clase de la clase donde se encuentra este método.
No importa cuántos objetos genera una clase, corresponden al mismo objeto de clase.
Programa de ejemplo 3
public class Threadtest {public static void main (string [] args) {ejemplo ejemplo = new Ejemplo (); Thread t1 = new Thread1 (ejemplo); // Incluso si se pasan diferentes objetos aquí, la sincronización del método estático todavía no permite que se ejecuten múltiples hilos al mismo tiempo. Ejemplo = nuevo ejemplo (); Thread t2 = new Thread2 (ejemplo); t1.start (); t2.start (); }} Ejemplo de clase {public sincronizado static void ejecute () {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("Hola:" + i); }} public sincronizado static void ejecutute2 () {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("World:" + i); }}} La clase Thread1 extiende el hilo {ejemplo privado de ejemplo; public Thread1 (ejemplo de ejemplo) {this.example = ejemplo; } @Override public void run () {ejemplo.ExeCute (); }} La clase Thread2 extiende el hilo {ejemplo privado de ejemplo; public Thread2 (ejemplo de ejemplo) {this.example = ejemplo; } @Override public void run () {ejemplo.Execute2 (); }} Entonces, si se trata de un método estático (ejecutar () y ejecute2 (), ambas tienen palabras clave estáticas agregadas), incluso si se pasan objetos de ejemplo diferentes a dos subprocesos, los dos hilos todavía están restringidos entre sí. Uno debe ser ejecutado primero y luego el siguiente.
en conclusión:
Si un método sincronizado es estático, cuando un hilo accede al método, no bloquea el objeto donde se encuentra el método sincronizado, sino el objeto de clase correspondiente a la clase donde se encuentra el método sincronizado. En Java, no importa cuántos objetos tenga una clase, estos objetos corresponderán a un objeto de clase único. Por lo tanto, cuando un hilo accede a dos métodos estáticos y sincronizados de dos objetos de la misma clase, su orden de ejecución también es secuencial, es decir, un hilo ejecuta primero el método y el otro hilo comienza después de que se complete la ejecución.
4. Bloque sincronizado
Método de escritura de bloques sincronizado:
sincronizado (objeto) {} Significa que el hilo bloqueará el objeto objeto cuando se ejecute. (Tenga en cuenta que este objeto puede ser un objeto de cualquier clase, o puede usar esta palabra clave).
De esta manera, puede especificar el objeto bloqueado usted mismo.
Programa de ejemplo 4
public class Threadtest {public static void main (string [] args) {ejemplo ejemplo = new Ejemplo (); Thread t1 = new Thread1 (ejemplo); Thread t2 = new Thread2 (ejemplo); t1.start (); t2.start (); }} Ejemplo de clase {objeto privado objeto = nuevo objeto (); public void ejecute () {sincronizado (objeto) {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("Hola:" + i); }}} public void ejecutute2 () {sincronizado (objeto) {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (InterruptedException e) {E.PrintStackTrace (); } System.out.println ("World:" + i); }}}}}} La clase Thread1 extiende el hilo {ejemplo privado de ejemplo; public Thread1 (ejemplo de ejemplo) {this.example = ejemplo; } @Override public void run () {ejemplo.ExeCute (); }} La clase Thread2 extiende el hilo {ejemplo privado de ejemplo; public Thread2 (ejemplo de ejemplo) {this.example = ejemplo; } @Override public void run () {ejemplo.Execute2 (); }} El efecto logrado por el programa de ejemplo 4 es el mismo que el del programa de ejemplo 2. Ambos hilos se ejecutan en secuencia, en lugar de simultáneamente. Cuando un hilo se ejecuta, el objeto se bloquea y el otro hilo no puede ejecutar el bloque correspondiente.
El método sincronizado es realmente equivalente a envolver todas las declaraciones en el método con un bloque sincronizado, y luego pasar esta palabra clave en los soportes del bloque sincronizado. Por supuesto, si se trata de un método estático, el objeto de clase debe bloquearse.
Quizás solo unas pocas líneas de código en un método implicarán problemas de sincronización de subprocesos, por lo que el bloque sincronizado controla el acceso de múltiples hilos de manera más granular que el método sincronizado. Solo no se puede acceder al contenido en el bloque sincronizado mediante múltiples hilos al mismo tiempo, y aún se puede acceder a otras declaraciones en el método mediante múltiples hilos al mismo tiempo (incluso antes y después del bloque sincronizado).
Nota: Los datos protegidos por sincronizado deben ser privados.
en conclusión:
El método sincronizado es un control concurrente de grano grueso. En un momento determinado, solo un hilo puede ejecutar el método sincronizado;
El bloque sincronizado es un control de concurrencia de grano fino, que solo sincroniza el código en el bloque. Se puede acceder a otros códigos ubicados en el método y que no sean bloques sincronizados mediante múltiples hilos al mismo tiempo.