Ocho escenarios de uso de métodos de sincronización
Análisis: este escenario es un bloqueo de método en un bloqueo de objeto clásico, es decir, dos subprocesos compiten por el mismo bloqueo de objeto, por lo que se esperan entre sí y son seguros para subprocesos.
Los métodos sincrónicos que permiten que dos subprocesos accedan al mismo objeto al mismo tiempo son seguros para subprocesos.
Esta situación es una situación de falla de bloqueo de objeto. El motivo del acceso es el método de sincronización de los dos objetos, y luego los dos subprocesos están controlados por los bloqueos de los dos subprocesos, por lo que no restringirán cada uno de ellos. otro. El propósito del bloqueo es permitir que varios subprocesos compitan por el mismo candado. En este caso, varios subprocesos ya no compiten por el mismo candado, sino que tienen candados diferentes, por lo que concluimos:
El método sincronizado. dos subprocesos que acceden a dos objetos al mismo tiempo no son seguros para subprocesos.
Resultados de la ejecución:
Dos subprocesos se ejecutan en paralelo, por lo que no es seguro para subprocesos.
Nombre del hilo: Thread-0, inicio de operación
Nombre del hilo: Thread-1, inicio de operación
Thread: Thread-0, fin de operación
Hilo: Hilo-1, fin de operación
Fin de prueba
Sincronización de dos hilos (hilo 1, hilo 2) accediendo a dos objetos (instancia1, instancia2) Método (), ambos subprocesos tienen sus propios bloqueos y no pueden formar una situación en la que dos subprocesos compitan por un bloqueo, por lo que en este momento, el efecto del método de modificación sincrónica () y el método sin modificación sincrónica () es el Lo mismo, entonces esto En este momento, el efecto del método sincronizado método () y el método asincrónico es el mismo (si no lo cree, puede eliminar la palabra clave sincronizada y el resultado será el mismo), por lo que en esta vez, método() es sólo un método normal.
Para que el bloqueo sea efectivo, solo necesita cambiar el método método () a estático, lo que creará un bloqueo de clase. Varias instancias (instancia1, instancia2) competirán por el mismo bloqueo de clase. Esto permite que dos subprocesos se ejecuten en serie. De eso se trata la siguiente escena.
Este escenario resuelve el problema de inseguridad de subprocesos visto en el escenario 2, que se implementa mediante bloqueos de clase:
Dos subprocesos acceden a la estática de (uno o dos) objetos al mismo tiempo Sincronizado Los métodos son seguros para subprocesos.
Suponiendo que uno de los dos subprocesos accede al método sincrónico y el otro accede al método asincrónico, ¿el programa se ejecutará en serie, es decir, es seguro para subprocesos?
Podemos estar seguros de que no es seguro para subprocesos. Si el método es seguro sin sincronización, entonces no es necesario utilizar el método sincronizado. Para verificar nuestra conclusión:
No es seguro para subprocesos que dos subprocesos accedan simultáneamente a métodos sincronizados y no sincronizados de (uno o dos) objetos respectivamente.
Los dos subprocesos se ejecutan en paralelo, por lo que no es seguro para subprocesos.
Nombre del hilo: Thread-0, método sincrónico, inicio de operación
Nombre del hilo: Thread-1, método normal, inicio de operación
Thread: Thread -0, método síncrono, fin de ejecución
Hilo: Thread-1, método normal, fin de ejecución
Fin de prueba
Aquí radica el problema: el método 1 no fue Se modifica sincrónicamente, por lo que no se ve afectado por los bloqueos. Incluso dentro del mismo objeto, ciertamente en múltiples instancias, es incluso menos probable que se vea afectado por bloqueos.
Conclusión:
Los métodos no sincronizados no se verán afectados por otros métodos sincronizados modificados por sincronizados
Puede pensar en un escenario similar: varios subprocesos acceden a un objeto sincronizado en el mismo método de objeto. y el método sincronizado llama a un método no sincronizado; ¿este escenario será seguro para subprocesos?
Probemos este escenario, usando dos subprocesos para llamar a un método sincronizado, llamando a un método normal dentro del método sincronizado y luego usando un subproceso para llamar al método normal directamente para ver si es seguro para subprocesos.
Nombre del hilo: Thread-0, método normal, comenzar a ejecutar
Nombre del hilo: Thread-1, método sincrónico, comenzar a ejecutar
Thread: Nombre del hilo: Thread-1, método de sincronización, finaliza la ejecución, comienza a llamar al método normal
Nombre del thread: Thread-1, método normal, comienza a ejecutarse
Nombre del thread: Thread-1, método normal, Comenzar a ejecutar
Hilo: Hilo 0, método normal, fin de operación
Hilo: Hilo 1, método normal, fin de operación
Nombre del hilo: Hilo 2 , Método de sincronización, inicio de operación
Hilo: Hilo 2, método sincrónico, fin de operación, comenzar a llamar al método normal
Nombre del hilo: Hilo 2, método normal, inicio de operación
Thread: Thread-2, método normal, fin de operación
Fin de prueba
Podemos ver que el método normal es ejecutado en paralelo por dos threads y no es seguro para subprocesos. ¿Por qué es esto?
Porque si cualquier otro subproceso llama directamente al método no sincronizado, en lugar de llamar al método no sincronizado solo cuando se llama al método sincronizado, entonces habrá múltiples subprocesos ejecutando el método no sincronizado. en paralelo, que no es seguro para subprocesos.
Para que los métodos sincronizados llamen a métodos no sincronizados, para garantizar la seguridad de los subprocesos, debe asegurarse de que la entrada del método no sincronizado solo aparezca en el método sincronizado. Sin embargo, este método de control no es lo suficientemente elegante. Si una persona desconocida llama directamente al método asincrónico, la sincronización del hilo original ya no será segura. Por lo tanto, no recomendamos que utilice este método en su proyecto, pero debemos comprender esta situación y debemos manejar la seguridad de los subprocesos de una manera semánticamente clara, para que la gente sepa de un vistazo que se trata de un método sincronizado.
Por lo tanto, la forma más sencilla es agregar la palabra clave sincronizada al método asincrónico para convertirlo en un método sincronizado, que se convierte en "Escenario 5: dos subprocesos acceden a diferentes métodos sincronizados del mismo objeto al mismo tiempo " En este caso, podemos ver claramente que no importa qué hilo llame a dos métodos sincronizados del mismo objeto, son seguros para subprocesos.
Si dos subprocesos acceden al método sincronizado del mismo objeto y el método sincronizado llama a un método no sincronizado, es seguro para subprocesos solo si ningún otro subproceso llama directamente al método no sincronizado. Si otros subprocesos llaman directamente a métodos asincrónicos, el subproceso no es seguro.
Este escenario también explora el alcance de los bloqueos de objetos, que se pueden utilizar para todos los métodos sincronizados en un objeto. Por lo tanto, al acceder a múltiples métodos sincronizados en el mismo objeto, la conclusión es:
Es seguro para subprocesos que dos subprocesos accedan a diferentes métodos sincronizados del mismo objeto al mismo tiempo.
Es seguro para subprocesos.
Nombre del hilo: Hilo-1, método de sincronización 1, comenzar a ejecutar
Hilo: Hilo-1, método de sincronización 1, finalizar la ejecución
Nombre del hilo: hilo -0, método de sincronización 0, la operación comienza
Hilo: Nombre del hilo: Hilo -0, método de sincronización 0, la operación finaliza
La prueba finaliza
Los modificadores de sincronización de los dos métodos (método0() y método1()) no especifican un objeto de bloqueo, pero el objeto de bloqueo predeterminado es este objeto como objeto de bloqueo
Por lo tanto, para la misma instancia, dos subprocesos obtienen Para el mismo bloqueo, los métodos sincronizados se ejecutarán en serie. Esto también refleja la naturaleza reentrante de la palabra clave sincronizada.
Nombre del hilo: Thread-0, método de sincronización estática 0, inicio
Nombre del hilo: Thread-1, método de sincronización no estática 1, inicio
Thread : Thread-1, método de sincronización no estática 1, fin
Thread: Thread-0, método de sincronización estática 0, end
Thread: p>
La prueba finaliza
Este ejemplo explora el problema de liberar un bloqueo mediante sincronización:
El bloqueo solo se libera cuando el método sincronizado completa la ejecución o se lanza una excepción durante la ejecución en ambos casos. liberar.
Entonces, cuando el método sincronizado de un subproceso genera una excepción, el bloqueo se libera y otro subproceso adquiere el bloqueo y continúa la ejecución. No habrá ninguna situación en la que un subproceso arroje una excepción mientras otro subproceso continúa esperando adquirir el bloqueo. Esto se debe a que cuando un método sincronizado genera una excepción, la JVM libera automáticamente el objeto de bloqueo.
Nombre del hilo: Thread-0, comenzar a ejecutar
Nombre del hilo: Thread-0, lanzar excepción, liberar bloqueo
Nombre del hilo: Thread-1, Ejecutar inicia
java.lang.RuntimeException ocurrió en el hilo "Thread-0"
en com.study.synchronize.conditions.Condition7.method0(Condition7.java: 34)
p>en com.study.synchronize.conditions.Condition7.run(Condition7.java:34)
Puede ver que el hilo todavía se está ejecutando en serie, lo que indica que es un hilo- seguro. Y cuando ocurre una excepción, no provocará un punto muerto. La JVM liberará automáticamente el objeto de bloqueo del subproceso de excepción y otros subprocesos adquirirán el bloqueo y continuarán con la ejecución.