Como herramienta para compartir datos simultáneamente y garantizar la coherencia, los bloqueos tienen múltiples implementaciones en la plataforma JAVA (como sincronizado y ReentrantLock, etc.). Estos candados ya escritos brindan comodidad para nuestro desarrollo, pero rara vez se mencionan la naturaleza y el tipo específicos de los candados. Esta serie de artículos analizará los nombres y características de bloqueos comunes en JAVA para responder sus preguntas.
4. Cerradura reentrante:
Este artículo habla sobre bloqueos reentrantes en un sentido amplio, no solo sobre ReentrantLock en JAVA.
Los bloqueos reentrantes, también llamados bloqueos recursivos, significan que después de que la función externa del mismo subproceso adquiere el bloqueo, la función recursiva interna todavía tiene el código para adquirir el bloqueo, pero no se ve afectada.
En el entorno JAVA, ReentrantLock y sincronizado son bloqueos reentrantes.
A continuación se muestran ejemplos de uso:
Copie el código de código de la siguiente manera:
La prueba de clase pública implementa Runnable{
get nulo público sincronizado(){
System.out.println(Thread.currentThread().getId());
colocar();
}
conjunto vacío sincronizado público(){
System.out.println(Thread.currentThread().getId());
}
@Anular
ejecución pública vacía() {
conseguir();
}
público estático vacío principal (String [] argumentos) {
Prueba ss=nueva prueba();
nuevo hilo(ss).start();
nuevo hilo(ss).start();
nuevo hilo(ss).start();
}
}
Los resultados finales de ambos ejemplos son correctos, es decir, el mismo ID de hilo se genera dos veces consecutivas.
El resultado es el siguiente:
Copie el código de código de la siguiente manera:
ID de hilo: 8
ID de hilo: 8
ID de hilo: 10
ID de hilo: 10
ID de hilo: 9
ID de hilo: 9
La función más importante de las cerraduras reentrantes es evitar puntos muertos.
Tomemos como ejemplo el bloqueo de giro.
Copie el código de código de la siguiente manera:
clase pública SpinLock {
propietario de AtomicReference<Thread> privado =new AtomicReference<>();
bloqueo de vacío público(){
Hilo actual = Thread.currentThread();
while(!propietario.compareAndSet(nulo, actual)){
}
}
desbloqueo público de vacío (){
Hilo actual = Thread.currentThread();
propietario.compareAndSet (actual, nulo);
}
}
Para cerraduras giratorias:
1. Si el mismo hilo llama a lock () dos veces, hará que la posición de bloqueo que se llame por segunda vez gire. Si se produce un punto muerto, significa que el bloqueo no es reentrante. (En la función de bloqueo, debes verificar si el hilo es el hilo que obtuvo el bloqueo)
2. Si se ha solucionado el problema 1, el bloqueo se habrá liberado cuando se llame a unlock() por primera vez. En realidad, el bloqueo no debería desbloquearse.
(Usando tiempos de conteo para estadísticas)
Después de la modificación, queda como sigue:
Copie el código de código de la siguiente manera:
clase pública SpinLock1 {
propietario de AtomicReference<Thread> privado =new AtomicReference<>();
recuento de int privado = 0;
bloqueo de vacío público(){
Hilo actual = Thread.currentThread();
if(actual==propietario.get()) {
contar++;
devolver ;
}
while(!propietario.compareAndSet(nulo, actual)){
}
}
desbloqueo público de vacío (){
Hilo actual = Thread.currentThread();
if(actual==propietario.get()){
si(cuenta!=0){
contar--;
}demás{
propietario.compareAndSet (actual, nulo);
}
}
}
}
Este bloqueo de giro es un bloqueo reentrante.