本文共 1699 字,大约阅读时间需要 5 分钟。
在分析Java并发包java.util.concurrent源码时,AbstractQueueSynchronizer(简称AQS)是一个不可或缺的核心组件,它是ReentrantLock、CountDownLatch、Semaphore等多个并发工具类的基础。通过深入分析ReentrantLock的公平锁实现,我们可以更好地理解AQS的工作原理。
AQS主要维护以下几个关键属性:
head:表示当前持有锁的线程,或者阻塞队列的首节点。tail:阻塞队列的末尾节点。state:表示锁的占有次数,值为0时表示锁未被占有,值大于0时表示有线程正在占用锁。exclusiveOwnerThread:表示当前独占锁的线程。AQS的阻塞队列采用的是FIFO(先进先出)的方式,每个线程被包装成一个Node实例,通过prev和next指针形成一个链表。每个节点还包含waitStatus,用于表示线程的等待状态。
每个节点包含以下属性:
thread:等待的线程。waitStatus:等待状态,取值为: CANCELLED(1):线程取消了对锁的等待。SIGNAL(-1):当前节点需要被唤醒,后续节点的线程可以无条件获取锁。CONDITION(-2):线程正等待在条件上(本文不分析条件)。PROPAGATE(-3):下一个获取共享锁的线程应无条件传播。prev:前驱节点。next:后继节点。一个典型的ReentrantLock使用示例:
public class OrderService { private static final ReentrantLock reentrantLock = new ReentrantLock(true); public void createOrder() { reentrantLock.lock(); try { // 业务逻辑 } finally { reentrantLock.unlock(); } }} ReentrantLock内部通过Sync内部类实现锁机制,Sync有两个实现:FairSync(公平锁)和NonfairSync(非公平锁)。这里我们聚焦于FairSync。
tryAcquire(int arg):
state增加,线程继续执行。acquireQueued(Node node, int arg):
parkAndCheckInterrupt():
shouldParkAfterFailedAcquire(Node pred, Node node):
waitStatus为SIGNAL,挂起当前线程。unparkSuccessor(Node node):
release(int arg):
tryRelease(int releases):
在并发环境下,ReentrantLock依赖于AQS来管理锁状态、维护等待队列和唤醒机制。AQS通过state、head、tail和Node节点实现锁的获取和释放,确保线程能够高效地竞争和占有锁资源。通过分析ReentrantLock的实现,我们可以更深入地理解AQS的工作原理及其在并发编程中的重要性。
转载地址:http://nchfk.baihongyu.com/