¿Entrarán en conflicto los bloqueos de clases y los bloqueos de objetos? ¿Entrarán en conflicto los bloqueos de objetos y los bloqueos privados? Ilustración a través de ejemplos.
1. Acuerdos relevantes
Para aclarar la siguiente descripción, primero hacemos las siguientes convenciones sobre las definiciones relevantes de bloqueos involucradas en este artículo:
1. Bloqueo de clase: agregue bloqueos estáticos y sincronizados a los métodos en el código, o segmentos de código sincronizados (xxx.class), como el incremento () a continuación;
2. Bloqueo de objeto: agregue un bloqueo sincronizado al método en el código, o un segmento de código sincronizado (este), como synOnMethod () y synInMethod () a continuación;
3. Bloqueo privado: declare una propiedad privada, como el bloqueo de objeto privado dentro de la clase, y sincronice (bloquee) el segmento de código que debe bloquearse, como synMethodWithObj() a continuación.
2. Código de prueba
1. Escribe una clase de inicio ObjectLock
Copie el código de código de la siguiente manera:
bloqueo de objeto de clase pública {
público estático vacío principal (String [] argumentos) {
System.out.println("hora de inicio = " + System.currentTimeMillis()+"ms");
Prueba LockTestClass = nueva LockTestClass();
para (int i = 0; i < 3; i++) {
Hilo hilo = nuevo ObjThread(prueba, i);
hilo.start();
}
}
}
2. Escriba una clase de subproceso ObjThread para iniciar el método de sincronización (tenga en cuenta que su método de ejecución puede ajustarse para diferentes pruebas)
Copie el código de código de la siguiente manera:
clase pública ObjThread extiende Thread {
Bloqueo LockTestClass;
int yo = 0;
público ObjThread (bloqueo LockTestClass, int i) {
this.lock = bloquear;
esto.i = i;
}
ejecución pública vacía() {
//Método sin bloqueo
//lock.noSynMethod(this.getId(),this);
// Método 1 de bloqueo de objetos, utilizando synInMethod sincronizado
lock.synInMethod();
// Método 2 de bloqueo de objetos, usando el método sincronizado (este)
//lock.synOnMethod();
//Método de bloqueo privado, utilizando el método sincronizado (objeto)
//lock.synMethodWithObj();
//Método de bloqueo de clase, utilizando el método de incremento sincronizado estático
LockTestClass.increment();
}
}
3. Escriba otra clase de prueba de bloqueo LockTestClass, incluidos varios métodos de bloqueo
Copie el código de código de la siguiente manera:
clase pública LockTestClass {
//Utilizado para contar bloqueos de clases
int estático privado i = 0;
//Bloqueo privado
objeto objeto privado = nuevo objeto();
/**
*<p>
* Método sin bloqueo
*
* @param ID de hilo
* hilo @param
*/
public void noSynMethod (ID de hilo largo, hilo ObjThread) {
System.out.println("nosyn: clase obj es " + hilo + ", threadId es"
+ ID de hilo);
}
/**
* Método de bloqueo de objetos 1
*/
público sincronizado vacío synOnMethod() {
System.out.println("synOnMethod comienza" + ", tiempo = "
+ System.currentTimeMillis() + "ms");
intentar {
Hilo.dormir(2000L);
} captura (Excepción interrumpida e) {
e.printStackTrace();
}
System.out.println("synOnMethod finaliza");
}
/**
* Método 2 de bloqueo de objetos, use sincronizado (esto) para bloquear
*/
método sintético vacío público() {
sincronizado (esto) {
System.out.println("synInMethod comienza" + ", tiempo = "
+ System.currentTimeMillis() + "ms");
intentar {
Hilo.dormir(2000L);
} captura (Excepción interrumpida e) {
e.printStackTrace();
}
System.out.println("synInMethod termina");
}
}
/**
* Método de bloqueo de objetos 3
*/
synMethodWithObj vacío público() {
sincronizado (objeto) {
System.out.println("synMethodWithObj comienza" + ", tiempo = "
+ System.currentTimeMillis() + "ms");
intentar {
Hilo.dormir(2000L);
} captura (Excepción interrumpida e) {
e.printStackTrace();
}
System.out.println("synMethodWithObj termina");
}
}
/**
* Bloqueo de clase
*/
incremento de vacío sincronizado estático público() {
System.out.println("clase sincronizada. i = " + i + ", tiempo = "
+ System.currentTimeMillis() + "ms");
yo ++;
intentar {
Hilo.dormir(2000L);
} captura (Excepción interrumpida e) {
e.printStackTrace();
}
System.out.println("la clase finaliza sincronizada.");
}
}
3. Resultados de la prueba
1. Para probar bloqueos de clases y bloqueos de objetos, modifique el método de ejecución de ObjectThread de la siguiente manera:
Copie el código de código de la siguiente manera:
ejecución pública vacía() {
//Método sin bloqueo
//lock.noSynMethod(this.getId(),this);
// Método 1 de bloqueo de objetos, utilizando synInMethod sincronizado
lock.synInMethod();
// Método 2 de bloqueo de objetos, usando el método sincronizado (este)
//lock.synOnMethod();
//Método de bloqueo privado, utilizando el método sincronizado (objeto)
//lock.synMethodWithObj();
//Método de bloqueo de clase, utilizando el método de incremento sincronizado estático
LockTestClass.increament();
}
Salida terminal:
Copie el código de código de la siguiente manera:
hora de inicio = 1413101360231ms
comienza synInMethod, tiempo = 1413101360233ms
finaliza el método synIn
clase sincronizada. i = 0, tiempo = 1413101362233ms.
comienza synInMethod, tiempo = 1413101362233ms
Extremos sincronizados de clase.
finaliza el método synIn
clase sincronizada i = 1, tiempo = 1413101364233ms
comienza synInMethod, tiempo = 1413101364233ms
Extremos sincronizados de clase.
finaliza el método synIn
clase sincronizada i = 2, tiempo = 1413101366234ms
Extremos sincronizados de clase.
Puede ver que el método de bloqueo de objetos (synInMothod) es 2 segundos más rápido que el método de bloqueo de clases (incremento) cuando se inicia por primera vez. Esto se debe a que cuando se ejecuta synInMehtod, duerme durante 2 segundos y luego ejecuta el incremento, y estos dos. Los métodos comparten el mismo hilo. Por lo tanto, será 2 segundos más lento si el incremento se coloca delante de synInMethod en ejecución, entonces el incremento será 2 segundos más rápido cuando se inicie por primera vez.
Cuando se inicia el método de bloqueo de clase, el método de bloqueo de objetos de otro hilo también se inicia casi al mismo tiempo, lo que indica que los dos no están usando el mismo bloqueo y no habrá competencia.
Conclusión: los bloqueos de clases y los bloqueos de objetos no competirán y sus métodos de bloqueo no se afectarán entre sí.
2. Bloqueos privados y bloqueos de objetos. El método de ejecución de ObjectThread se modifica de la siguiente manera:
Copie el código de código de la siguiente manera:
ejecución pública vacía() {
//Método sin bloqueo
//lock.noSynMethod(this.getId(),this);
// Método 1 de bloqueo de objetos, utilizando synInMethod sincronizado
lock.synInMethod();
// Método 2 de bloqueo de objetos, usando el método sincronizado (este)
//lock.synOnMethod();
//Método de bloqueo privado, utilizando el método sincronizado (objeto)
lock.synMethodWithObj();
//Método de bloqueo de clase, utilizando el método de incremento sincronizado estático
//LockTestClass.increament();
}
Salida terminal:
Copie el código de código de la siguiente manera:
hora de inicio = 1413121912406ms
Comienza synInMethod, tiempo = 1413121912407ms.
synInMethod finaliza.
comienza synMethodWithObj, tiempo = 1413121914407ms
Comienza synInMethod, tiempo = 1413121914407ms.
synInMethod finaliza.
synMethodWithObj termina
Comienza synInMethod, tiempo = 1413121916407ms.
comienza synMethodWithObj, tiempo = 1413121916407ms
synInMethod finaliza.
synMethodWithObj termina
comienza synMethodWithObj, tiempo = 1413121918407ms
synMethodWithObj termina
Muy similar a los bloqueos de clases y de objetos.
Conclusión: los bloqueos privados y los bloqueos de objetos no competirán y sus métodos de bloqueo no se afectarán entre sí.
3.Synchronized se agrega directamente al método y se sincroniza (esto), y el método de ejecución de ObjectThread se modifica de la siguiente manera:
Copie el código de código de la siguiente manera:
ejecución pública vacía() {
//Método sin bloqueo
//lock.noSynMethod(this.getId(),this);
// Método 1 de bloqueo de objetos, utilizando synInMethod sincronizado
lock.synInMethod();
// Método 2 de bloqueo de objetos, usando el método sincronizado (este)
lock.synOnMethod();
//Método de bloqueo privado, utilizando el método sincronizado (objeto)
//lock.synMethodWithObj();
//Método de bloqueo de clase, utilizando el método de incremento sincronizado estático
//LockTestClass.increament();
}
Salida terminal:
Copie el código de código de la siguiente manera:
hora de inicio = 1413102913278ms
comienza synInMethod, tiempo = 1413102913279ms
finaliza el método synIn
comienza synInMethod, tiempo = 1413102915279ms
finaliza el método synIn
comienza synOnMethod, tiempo = 1413102917279ms
synOnMethod finaliza
comienza synInMethod, tiempo = 1413102919279ms
finaliza el método synIn
comienza synOnMethod, tiempo = 1413102921279ms
synOnMethod finaliza
comienza synOnMethod, tiempo = 1413102923279ms
synOnMethod finaliza
Como puede ver, los dos salen estrictamente en serie (por supuesto, no se determina si synInMethod o synOnMethod se ejecuta primero cuando se ejecuta nuevamente, dependiendo de quién obtenga el bloqueo).
Conclusión: sincronizado agregado directamente al método y sincronizado (esto) bloquean el objeto actual. Los dos métodos de bloqueo están en una relación competitiva y solo se puede ejecutar un método al mismo tiempo.