AbstractQueuedSynchronizer(简称AQS)是一个抽象同步框架,可以用来实现一个依赖状态的同步器。它通过一个内部类Sync继承AQS,将同步器所有调用都映射到Sync对应的方法,从而实现了阻塞等待队列、共享/独占、公平/非公平、可重入等行为。
ReentrantLock是JDK中提供的一种基于AQS框架的应用实现,是线程并发访问的同步手段。它具备互斥和同步的功能,同一时刻只允许一个线程访问共享资源,线程之间通过协作实现同步。
ReentrantLock提供了公平和非公平锁,以及可重入锁的实现。当前线程如果获取同步状态失败时,AQS会将当前线程已经等待状态等信息构造成一个节点,并将其加入到CLH同步队列,同时会阻塞当前线程。当同步状态释放时,会把首节点唤醒,使其再次尝试获取同步状态。
ReentrantLock的公平锁和非公平锁的实现主要是通过lock()和unlock()方法的调用时机来实现的。公平锁会按照线程请求锁的顺序来释放锁,因此公平性更好。而非公平锁则不保证解锁的顺序与锁请求的顺序一致,因此会有一定的竞争。
ReentrantLock通过AQS框架实现,它提供了公平锁和非公平锁两种锁机制。在实现上,当当前线程获取同步状态失败时,AQS会将当前线程已经等待状态等信息构造成一个节点并将其加入到CLH同步队列中,同时会阻塞当前线程。当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态。
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private final ReentrantLock lock = new ReentrantLock(true); // 创建公平锁实例
private final ReentrantLock lockNonFair = new ReentrantLock(); // 创建非公平锁实例
public void method() {
lock.lock(); // 获取公平锁
try {
// 公平锁保护的代码段
} finally {
lock.unlock(); // 释放公平锁
}
lockNonFair.lock(); // 获取非公平锁
try {
// 非公平锁保护的代码段
} finally {
lockNonFair.unlock(); // 释放非公平锁
}
}
}
Remind:
ReentrantLock类创建了公平锁和非公平锁实例,并在方法中分别使用它们来保护不同的代码段。注意,在使用锁时需要调用
lock()
方法获取锁,并在finally
块中调用unlock()
方法释放锁,以确保代码块的正确执行。
ReentrantLock的可重入锁是指同一个线程可以多次获取同一个锁,而不会产生死锁。在ReentrantLock中,当一个线程已经获取了锁,再次请求获取该锁时,会返回该线程已经持有的锁,从而实现可重入锁的功能。
这段代码中,ReentrantLock构造函数中的true参数表示这是一个可重入锁。当一个线程已经获取了锁,再次调用lock()方法时,会返回这个线程已经持有的锁,从而允许该线程再次获取锁。
public class ReentrantLockExample {
private final ReentrantLock lock = new ReentrantLock(true); // true表示可重入锁
public void doSomething() {
lock.lock(); // 获取锁
try {
// ... 方法体
} finally {
lock.unlock(); // 释放锁
}
}
}
AQS内部维护了一个volatile int state的状态变量,定义了两种资源访问方式:AQS实现时主要实现以下几种方法:Acquire, TryAcquire, Release, HasQueuedThreads, HasWaiters等。AQS定义了5个队列中节点状态:Node、WaitNode、WaitSetNode、SignalNode等。这些队列和节点状态为线程之间的同步提供了基础。
ReentrantLock是JDK中基于AQS框架实现的一种独占锁,具备互斥和同步的功能。它的使用方式简单,支持公平和非公平锁,以及可重入锁的实现。AQS是一个抽象同步框架,提供了基础的行为等待队列、条件队列、独占获取、共享获取等,这些行为的抽象为线程之间的同步提供了可能。在设计和实现并发程序时,了解和掌握这些基础知识和工具是非常重要的。