El método de sincronización más básico de Java es usar la palabra clave sincronizada para controlar el acceso concurrente de un método. Cada método declarado con la palabra clave sincronizada es una sección crítica. En Java, solo se permite acceder a una de las secciones críticas del mismo objeto al mismo tiempo.
Los métodos estáticos tienen comportamientos diferentes. Un método estático declarado con la palabra clave sincronizada solo puede acceder mediante un hilo de ejecución, pero otros subprocesos pueden acceder al método sincronizado no estático de este objeto. Esto debe ser muy cauteloso porque dos hilos pueden acceder a dos métodos sincronizados diferentes de un objeto al mismo tiempo, es decir, uno de los cuales es un método sincronizado estático y el otro es un método sincronizado no estático. Si ambos métodos cambian los mismos datos, se producirá un error inconsistente.
La sintaxis del bloque sincronizado es la siguiente:
Public void Method () {Synchronized (Expression) {}} Hay dos usos de la palabra clave sincronizada. Uno solo se usa en la definición de métodos, y el otro es el bloque sincronizado. No solo podemos usar sincronizados para sincronizar una variable de objeto, sino que también puede usar SynchronizedL para sincronizar los métodos estáticos y los métodos no estáticos en la clase.
El primero: sincronización de métodos no estáticos
De la sintaxis relacionada con Java, podemos saber que el uso de la palabra clave sincronizada para definir un método bloqueará los métodos estáticos y los métodos no estatales definidos por la palabra clave Synchroniezd en la clase, pero esto es un poco difícil de entender. Si desea sincronizar bloques para lograr tal efecto, no es difícil entender por qué se produce este efecto. Si usa sincronizado para bloquear todos los métodos no estáticos sincronizados en la clase, solo necesita usar esto como el parámetro del bloque sincronizado para pasar al bloque sincronizado. El código es el siguiente:
Prueba de clase pública {public void método1 () {sincronizado (this) {}} public sincronizado Void Method2 () {}} Test de clase pública {public void Method1 () {SynConized (this) {}} public sincronizado Void Method2 ()}}} En el código anterior, Method1 usa el bloque sincronizado, y el método Method2 usa la palabra clave sincronizada para definir el método. Si usa la misma instancia de prueba, mientras se ejecute uno de estos dos métodos, los otros métodos se bloquearán porque no han obtenido el bloqueo de sincronización. Además de usar esto como el parámetro del bloque sincronizado, también puede usar la prueba. Este es el parámetro del bloque sincronizado para lograr el mismo efecto.
Al usar bloques sincronizados en clases internas, esto solo representa clases internas y no tiene nada que ver con las clases externas (clase externas). Sin embargo, los métodos no estatales en las clases internas y los métodos no estáticos en las clases externas también se pueden sincronizar. Si agrega un método método3 a la clase interna, también puede sincronizarse con los dos métodos en la prueba, el código es el siguiente:
Public Class Test {Class InnClass {public void Method3 () {SynChronized (test.this) {}}} public class test {Class InnClass {public void Method3 () {Synchronized (test.this) {}}}}} El método Method3 de InnClass anterior y los métodos de prueba Method1 y Method2 solo pueden tener un método ejecutado al mismo tiempo.
Ya sea que el bloque sincronizado se ejecute correctamente o el bloque sincronizado salga debido a una excepción debido a un error de programa, el bloqueo de sincronización sostenido por el bloque sincronizado actual se lanzará automáticamente. Por lo tanto, no tiene que preocuparse por el bloqueo de sincronización al usar el bloque sincronizado.
2. Sincronización de métodos estáticos
Dado que las instancias de objetos no se crean necesariamente al llamar a los métodos estáticos, esto no puede usarse para sincronizar los métodos estáticos, sino que debe usar objetos de clase para sincronizar los métodos estáticos. El código es el siguiente:
Public Class Test {public static void Method1 () {Synchronized (test.class) {}} public static static sincronized void método2 () {}} public class test {public static void método1 () {sincronizado (test.class) {}} public sincronizado Method2 () {}}}}}}}}}}Al sincronizar los métodos estáticos, puede usar la clase de campo estático de la clase para obtener el objeto de clase. En el ejemplo anterior, solo hay una ejecución del método de métodos Method1 y Method2. Además de usar el campo de clase, también puede obtener el objeto de clase a través del método getClass () de la instancia. El código es el siguiente:
Prueba de clase pública {prueba de prueba estática pública; Public test () {test = this; } public static void Method1 () {SynChronized (test.getClass ()) {}} Test de clase pública {prueba de prueba estática pública; Public test () {test = this; } public static void Method1 () {Synchronized (test.getClass ()) {}}}
En el código anterior, obtenemos una instancia de prueba a través de un objeto estático público y obtenemos un objeto de clase a través del método GetClass de esta instancia (tenga en cuenta que todas las instancias de una clase se obtienen a través del método GetClass). También podemos sincronizar métodos estáticos de diferentes clases a través de la clase, el código es el siguiente:
public class test1 {public static void Method1 () {Synchronized (test.class) {}}} public class test1 {public static void Method1 () {sincronizado (test.class) {}}}
Nota: Cuando se usan bloques sincronizados para sincronizar los métodos, los métodos no estáticos se pueden sincronizar a través de esto, mientras que los métodos estáticos deben sincronizarse usando objetos de clase, pero los métodos no estatales también se pueden sincronizar mediante el uso de la clase. Sin embargo, esto no puede usarse en métodos estáticos para sincronizar métodos no estáticos. Esto debe prestarse atención cuando se usa bloques sincronizados.
Nota
La palabra clave sincronizada degradará el rendimiento de la aplicación y, por lo tanto, solo se puede utilizar en métodos que requieren modificar los datos compartidos en escenarios concurrentes. Si múltiples hilos acceden al mismo método sincronizado, solo un hilo puede acceder a él y los otros hilos esperarán. Si la declaración del método no usa la palabra clave sincronizada, todos los subprocesos pueden ejecutar el método al mismo tiempo, reduciendo así el tiempo de ejecución total. Si se sabe que es llamado por más de un hilo, no necesita declararlo usando la palabra clave sincronizada.
Los métodos declarados sincronizados pueden llamarse recursivamente. Cuando un hilo accede al método de sincronización de un objeto, también puede llamar a otros métodos de sincronización del objeto, incluido el método de ejecución, sin tener que obtener acceso al método nuevamente.
Podemos proteger el acceso a los bloques de código (en lugar de todo el método) a través de la palabra clave sincronizada. La palabra clave sincronizada debe usarse así: el resto del método permanece fuera del bloque de código sincronizado para un mejor rendimiento. El acceso a la sección crítica (es decir, bloques de código a los que solo se puede acceder a un hilo al mismo tiempo) debe ser lo más corto posible. Por ejemplo, en la operación de obtener el número de personas en un edificio, solo usamos la palabra clave sincronizada para proteger las instrucciones para actualizar el número de personas y hacer que otras operaciones no usen datos compartidos. Al usar palabras clave sincronizadas de esta manera, la referencia del objeto debe usarse como un parámetro entrante. Solo un hilo puede acceder a este código sincronizado al mismo tiempo. En términos generales, usamos esta palabra clave para referirnos al objeto al que pertenece el método que se ejecuta:
sincronizado (this) {// código java}