Cerraduras reentrantes (cerraduras exclusivas, cerraduras de exclusión mutua)
La interfaz del paquete juc define la especificación de bloqueo. Hay varias clases de implementación.
ReentrantLock vuelve a bloquear el hilo que sujeta el candado antes de liberarlo. Si este hilo accede nuevamente a otros métodos de bloqueo de sincronización, este hilo no necesita competir por el bloqueo nuevamente, solo necesita registrar el número de reingresos. Las cerraduras de reentrada están diseñadas para resolver el problema del punto muerto.
El método inr() adquiere con éxito el bloqueo y llama a dec() para adquirir el bloqueo nuevamente sin liberarlo. Si no se vuelve a ingresar el bloqueo, se producirá un punto muerto. Si este hilo accede nuevamente a otros métodos de bloqueo de sincronización, este hilo no necesita competir por el bloqueo nuevamente, solo necesita registrar el número de reingresos.
ltspan style='color:rojo'gt. ¿Cómo se implementa internamente? ¿Qué debo hacer si el bloqueo de interrupción del hilo no se libera a tiempo? /spangt.
Implementación principal del bloqueo reentrante síncrono no aéreo
AQS mantiene una lista enlazada de doble extremo con un nodo principal y un nodo final. Crea un nodo Nodo para almacenar el hilo actual. Si hay un nodo de cola, intente cas para agregar el nodo actual al nodo de cola de la lista vinculada. Si no hay un nodo de cola, inicie cas para crear un nodo principal y gire (un bucle sin ninguna condición final) cas para agregar el nodo de cola al final de la lista vinculada y finalmente devuelva el nodo recién agregado.
Para el nodo insertado en la cola de espera, después de agregar el hilo a la lista vinculada mediante el método addWaiter, el nodo se pasará como parámetro al método adquirirQueued para competir por el bloqueo nuevamente.
Suspender el hilo actual. Aquí llame a LockSupport.park(this) para suspender el hilo y devuelva Thread.interrupted() para restablecer el hilo.
La lógica empresarial de liberar el bloqueo no necesita considerar subprocesos múltiples y aún está en manos de un subproceso. Porque el mecanismo de liberación del estado de bloqueo reentrante >:=1 es getState()-releases, que es el último valor con el nuevo estado y se devuelve si estado=0.