Copie el código de código de la siguiente manera:
ejecución vacía sincronizada pública ()
{
}
Como se puede ver en el código anterior, siempre que se agregue la palabra clave sincronizada entre void y public, el método de ejecución se puede sincronizar, es decir, para la instancia de objeto de la misma clase Java, el método de ejecución solo se puede sincronizar. llamado por un subproceso al mismo tiempo, y otros subprocesos pueden llamarlo solo después de que se ejecute la ejecución actual. Incluso si el hilo actual ejecuta el método de rendimiento en el método de ejecución, solo se detiene por un tiempo. Dado que otros subprocesos no pueden ejecutar el método de ejecución, el subproceso actual eventualmente continuará con la ejecución. Primero eche un vistazo al siguiente código:
La palabra clave sincronizada solo está vinculada a una instancia de objeto
Copie el código de código de la siguiente manera:
prueba de clase
{
método vacío sincronizado público ()
{
}
}
la clase pública Sync implementa Runnable
{
prueba de prueba privada;
ejecución pública vacía()
{
prueba.método();
}
Sincronización pública (prueba de prueba)
{
this.test = prueba;
}
public static void main (String[] args) lanza una excepción
{
Prueba prueba1 = nueva prueba();
Prueba prueba2 = nueva prueba();
Sincronización sincronización1 = nueva sincronización (prueba1);
Sincronización sincronización2 = nueva sincronización (prueba2);
nuevo hilo(sync1).start();
nuevo hilo(sync2).start();
}
}
Los métodos de la clase Test son sincrónicos. Pero el código anterior crea dos instancias de la clase Test, por lo que los métodos de test1 y test2 se ejecutan por separado. Para sincronizar los métodos, debes pasar una instancia de la misma clase Test a su constructor al crear una instancia de la clase Sync, como se muestra en el siguiente código:
Sincronización sincronización1 = nueva sincronización (prueba1);
No solo puede usar sincronizado para sincronizar métodos no estáticos, sino que también puede usar sincronizado para sincronizar métodos estáticos. Por ejemplo, el método método se puede definir de la siguiente manera:
Copie el código de código de la siguiente manera:
prueba de clase
{
método público estático sincronizado void() { }
}
Cree una instancia de objeto de la clase Test de la siguiente manera:
Prueba prueba = nueva prueba();
Para los métodos estáticos, siempre que se agregue la palabra clave sincronizada, el método está sincronizado. Ya sea que use test.method () o Test.method () para llamar al método, el método está sincronizado y no existe. instancias de métodos no estáticos.
Entre los 23 patrones de diseño, el modo Singleton tampoco es seguro para subprocesos si se diseña de acuerdo con los métodos tradicionales. El siguiente código es un modo Singleton no seguro para subprocesos.
Copie el código de código de la siguiente manera:
prueba de paquete;
// Modo Singleton seguro para subprocesos
clase singleton
{
muestra Singleton estática privada;
singleton privado()
{
}
getInstance público estático Singleton ()
{
si (muestra == nulo)
{
Thread.yield(); // Para amplificar la inseguridad del hilo del modo Singleton
muestra = nuevo Singleton();
}
devolver muestra;
}
}
clase pública MyThread extiende Thread
{
ejecución pública vacía()
{
Singleton singleton = Singleton.getInstance();
System.out.println(singleton.hashCode());
}
principal vacío estático público (String [] argumentos)
{
Hilos de hilo[] = nuevo hilo[5];
para (int i = 0; i < threads.length; i++)
hilos[i] = nuevo MiHilo();
para (int i = 0; i < threads.length; i++)
hilos[i].start();
}
}
El método de rendimiento se llama en el código anterior para hacer que aparezca la inseguridad del subproceso del modo singleton. Si se elimina esta línea, la implementación anterior sigue siendo insegura para el subproceso, pero la posibilidad de que ocurra es mucho menor.
Los resultados de ejecutar el programa son los siguientes:
Copie el código de código de la siguiente manera:
25358555
26399554
7051261
29855319
5383406
Los resultados de ejecución anteriores pueden ser diferentes en diferentes entornos de ejecución, pero generalmente las cinco líneas de salida no serán exactamente iguales. Como se puede ver en este resultado, hay cinco instancias de objetos obtenidas mediante el método getInstance, no una como esperábamos. Esto se debe a que cuando un subproceso ejecuta Thread.yield(), entrega los recursos de la CPU a otro subproceso. Dado que la declaración para crear una instancia de objeto Singleton no se ejecuta al cambiar entre subprocesos, todos estos subprocesos pasan el juicio if, por lo que se crearán cinco instancias de objeto (se pueden crear cuatro o tres instancias de objeto, dependiendo de cuántos subprocesos pasen). el juicio if antes de crear el objeto Singleton, el resultado puede ser diferente cada vez que se ejecuta).
Para que el modo singleton anterior sea seguro para subprocesos, simplemente agregue la palabra clave sincronizada a getInstance. El código es el siguiente:
público estático sincronizado Singleton getInstance() { }
Por supuesto, existe una forma más sencilla, que consiste en crear un objeto Singleton al definir la variable Singleton. El código es el siguiente:
muestra Singleton final estática privada = new Singleton();
Luego simplemente devuelva la muestra directamente en el método getInstance. Aunque este método es simple, no es flexible al crear un objeto Singleton en el método getInstance. Los lectores pueden optar por utilizar diferentes métodos para implementar el patrón singleton según sus necesidades específicas.
Hay cuatro puntos a tener en cuenta al utilizar la palabra clave sincronizada:
1. La palabra clave sincronizada no se puede heredar.
Aunque puede utilizar sincronizado para definir métodos, sincronizado no forma parte de la definición del método, por lo que la palabra clave sincronizada no se puede heredar. Si un método en la clase principal usa la palabra clave sincronizada y anula este método en la subclase, el método en la subclase no está sincronizado de forma predeterminada y debe especificarse explícitamente en la subclase. Simplemente agregue la palabra clave sincronizada al método. Por supuesto, también puede llamar al método correspondiente en la clase principal en el método de la subclase. De esta manera, aunque el método en la subclase no es sincrónico, la subclase llama al método de sincronización de la clase principal. La subclase es equivalente a la sincronización. Los códigos de ejemplo para estos dos métodos son los siguientes:
Agregue la palabra clave sincronizada al método de subclase
Copie el código de código de la siguiente manera:
clase padre
{
método vacío sincronizado público () {}
}
clase Niño extiende Padre
{
método vacío sincronizado público () {}
}
Llame al método sincronizado de la clase principal en el método de la subclase
Copie el código de código de la siguiente manera:
clase padre
{
método vacío sincronizado público () {}
}
clase Niño extiende Padre
{
método público vacío() { super.método();
}
2. La palabra clave sincronizada no se puede utilizar al definir métodos de interfaz.
3. El constructor no puede usar la palabra clave sincronizada, pero puede usar el bloque sincronizado que se discutirá en la siguiente sección para la sincronización.
4. sincronizado se puede colocar libremente.
En los ejemplos anteriores, la palabra clave sincronizada se coloca delante del tipo de retorno del método. Pero este no es el único lugar donde se pueden colocar sincronizados. En métodos no estáticos, sincronizado también se puede colocar al frente de la definición del método. En métodos estáticos, sincronizado se puede colocar delante de estático.
Copie el código de código de la siguiente manera:
método vacío sincronizado público();
método de anulación pública sincronizada();
método público estático sincronizado void();
método vacío estático sincronizado público ();
método vacío estático público sincronizado();
Pero tenga en cuenta que sincronizado no se puede colocar después del tipo de retorno del método. Por ejemplo, el siguiente código es incorrecto:
Copie el código de código de la siguiente manera:
método público sincronizado vacío();
método público sincronizado vacío estático();
La palabra clave sincronizada solo se puede usar para sincronizar métodos, no variables de clase. El siguiente código también es incorrecto.
Copie el código de código de la siguiente manera:
público sincronizado int n = 0;
público estático sincronizado int n = 0;
Aunque utilizar el método de sincronización de palabras clave sincronizadas es el método de sincronización más seguro, el uso extensivo de la palabra clave sincronizada provocará un consumo innecesario de recursos y una pérdida de rendimiento. Aunque en la superficie parece que sincronizado bloquea un método, de hecho sincronizado bloquea una clase. En otras palabras, si se utiliza sincronizado al definir los métodos no estáticos método1 y método2, el método2 no se puede ejecutar antes de que se ejecute el método1. La situación es similar para los métodos estáticos y no estáticos. Pero los métodos estáticos y no estáticos no se afectan entre sí. Eche un vistazo al siguiente código:
Copie el código de código de la siguiente manera:
prueba de paquete;
la clase pública MyThread1 extiende Thread
{
Nombre del método de cadena pública;
método público estático vacío (String s)
{
System.out.println(s);
mientras (verdadero)
}
método vacío sincronizado público1 ()
{
método ("método método1 no estático");
}
método vacío sincronizado público2()
{
método ("método método2 no estático");
}
método vacío sincronizado estático público3()
{
método("método método estático3");
}
método vacío sincronizado estático público4()
{
método ("método estático4 método");
}
ejecución pública vacía()
{
intentar
{
getClass().getMethod(nombredelmétodo).invoke(esto);
}
captura (Excepción e)
{
}
}
public static void main (String[] args) lanza una excepción
{
MiHilo1 miHilo1 = nuevo MiHilo1();
para (int i = 1; i <= 4; i++)
{
myThread1.methodName = "método" + String.valueOf(i);
nuevo Hilo(miHilo1).start();
dormir(100);
}
}
}
Los resultados de ejecución son los siguientes:
Copie el código de código de la siguiente manera:
Método método1 no estático
Método método estático3
Como se puede ver en los resultados de ejecución anteriores, el método 2 y el método 4 no se pueden ejecutar antes de que se completen el método 1 y el método 3. Por lo tanto, podemos sacar la conclusión de que si usa la palabra clave sincronizada para definir un método no estático en una clase, afectará todos los métodos no estáticos definidos usando la palabra clave sincronizada en esta clase. Si se define un método estático, afectará a todos los métodos estáticos definidos utilizando la palabra clave sincronizada en la clase. Esto es un poco como un bloqueo de tabla en una tabla de datos. Cuando se modifica un registro, el sistema bloquea toda la tabla. Por lo tanto, el uso extensivo de este método de sincronización reducirá significativamente el rendimiento del programa.