Lectura del código fuente de AQS
Hoy, a partir del método de bloqueo de ReentrantLock, profundizaremos un poco en AQS para ver cómo AQS logra el propósito de bloquear y desbloquear. Primero, pruebe qué sucede cuando solo un hilo se bloquea y luego pruebe cómo lidiar con múltiples hilos. . y, por último, observe cómo la operación de desbloqueo activa otros subprocesos.
solo un hilo
código de prueba
public class TestReentantLock {
static ReentrantLock lock = new ReentrantLock(true);
static Runnable r1 = ()-> {
// 断点位置
lock.lock();
};
public static void main(String[] args) {
new Thread(r1).start();
}
}
复制代码
Proceso de implementación
Resumir
A través de este proceso puedes obtener:
- Cuando solo hay un subproceso, el valor del estado se establece a través de CAS, lo que indica que el bloqueo actual está en manos de un subproceso
- Cuando solo hay un hilo, las operaciones de nodos y colas no están involucradas.
cuando dos hilos
código de prueba
package process;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class TestReentantLock {
static ReentrantLock lock = new ReentrantLock(true);
static Runnable r1 = ()-> {
lock.lock();
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
};
static Runnable r2 = ()->{
// 断点位置
lock.lock();
};
public static void main(String[] args) throws InterruptedException {
new Thread(r1).start();
TimeUnit.SECONDS.sleep(1);
new Thread(r2).start();
}
}
复制代码
Proceso de implementación
Resumir
- Cuando hay dos subprocesos, use LockSupport.park() para suspender el subproceso para lograr el propósito de no adquirir el bloqueo
- Al establecer el valor waitStatus del nodo anterior en Node.Signal en -1, significa despertar el nodo posterior, es decir, a sí mismo.
operación de desbloqueo ()
código de prueba
package process;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class TestReentantLock {
static ReentrantLock lock = new ReentrantLock(true);
static Runnable r1 = ()-> {
lock.lock();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 断点处
lock.unlock();
};
static Runnable r2 = ()->{
lock.lock();
};
public static void main(String[] args) throws InterruptedException {
new Thread(r1).start();
TimeUnit.MILLISECONDS.sleep(500);
new Thread(r2).start();
}
}
复制代码
Proceso de implementación
Resumir
- Obtenga el nodo principal y use el estado de espera del nodo principal para determinar el desbloqueo de subprocesos posteriores
Resumir
La forma en que AQS logra la sincronización de subprocesos se puede resumir de la siguiente manera:
- Bloquee el hilo a través de LockSupport.park() para lograr el propósito de no poder adquirir el bloqueo
- Actualice atómicamente la cabeza y la cola de la cola a través de CAS
- A través de un estado volátil se logra el propósito de identificar el estado de la cerradura