1 AQS定义:

AQS是Java并发包java.util.concurrent.locks中一个核心并发框架,用于构建锁和同步器,

如:

  • ReentrantLock
  • ReentrantReadWriteLock
  • CountDownLatch
  • Semaphore
  • FutureTask

           image

2 AQS核心元素

2.1 state

volatile修饰整型关键字state,用来标识资源的占用状态(如是否被锁定),类似信号灯指挥线程的行动。

以ReentrantLock为例:state=0表示锁空闲,线程可以去竞争锁;state=1 表示有线程已经获取该锁,其他线程不可再获取整个锁,如果是同一线程再次获取,state会累加。只有state降为0后锁才会释放,其他线程才有机会获得锁

以CountDownLatch为例:state充当计数器,初始值设置为正数,比如设置为5,每个线程调用countDown()方法,state就会减1,等到state=0,那些因为调用await()方法而阻塞的线程就会被唤醒,尝试获取锁

state提供方法:

① getState() 线程安全查看state当前值

②setState() 线程安全给state设置新值,靠volatile保证线程安全

③compareAndSetState()使用CAS操作更新state,只有预期值和当前位置值一样才会修改,保证原子性,底层靠Usafe类调用CPU指令来实现该操作

2.2 FIFO队列

FIFO队列是一个双向链表结构,由一个个Node节点串联。当线程尝试获取资源tryAquire()失败后就会被封装成Node节点,通过addWaiter()方法加入队列尾巴。一旦进入队列,线程进入等待状态就等待被唤醒

FIFO队列关键属性:

head:同步队列的头节点,头节点指向真正持有锁资源的节点,后续节点只有等待head节点释放资源来唤醒自己

tail: 尾节点,最新来的进程会置为尾节点

node:作为同步队列和条件队列里的节点,它内部属性丰富得很。除了前面提到的 waitStatus、prev、next 和 thread,还有 nextWaiter,这是在条件队列里用的,指向节点的下一个等待者

 

head -> Node1 -> Node2 -> ... -> tail

           image

2.3获取/释放方法

核心方法: 

// 共享模式
protected int tryAcquireShared(int arg);
protected boolean tryReleaseShared(int arg);

// 独占模式
protected boolean tryAcquire(int arg);
protected boolean tryRelease(int arg);

 

获取锁流程:调用tryAcquire()方法,如果返回true线程获取到锁,如果返回false说明资源被占,线程被封装成Node节点,通过addWaiter()方法加入队列尾巴,接着在acquireQueued方法陷入自旋,在队列中自旋检查前驱节点是否为头节点并尝试获取资源,如果获取成功,将自己设为头节点

 

释放锁流程:调用tryRelease()方法,如果释放成功,唤醒后继节点中的线程

2.3.1 tryAcquire()--Reentrant Lock为例--独占模式(ReentrantLock分为公平锁和非公平锁):

ReentrantLock的tryAcquire()实现如下:

非公平锁:线程一开始不管队列里有没有前节点,先执行CAS操作,如果state=0,就会抢占锁,然后把state置为1,顺便把当前线程标记成独占锁;如果state=1判断是否是不是自己已经拿到的锁,如果是state++体现可重入特性。如果失败则入队挂起

公平锁:线程先判断是否有前节点,如果没有才会去抢锁,如果有则继续排队挂起线程,只有被前驱节点唤醒后再次尝试获取锁

 非公平tryAcquire实现代码

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        // 尝试直接 CAS 获取锁
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    } else if (current == getExclusiveOwnerThread()) {
        // 可重入,加重入次数
        int nextc = c + acquires;
        setState(nextc);
        return true;
    }
    return false;
}
View Code

 

公平锁tryAcquire实现代码

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (!hasQueuedPredecessors() &&  // 关键点:检查是否有等待更久的线程
            compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    // ...重入逻辑
    return false;
}

public final boolean hasQueuedPredecessors() {
    Node t = tail;
    Node h = head;
    Node s;
    return h != t &&  // 队列不为空
        ((s = h.next) == null || s.thread != Thread.currentThread());
}
View Code

 

2.3.2 tryRelease

只有state=0才会调用释放锁

protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}
View Code

 

 

AQS 线程状态控制核心机制:LockSupport

AQS 底层通过 LockSupport.park() 和 unpark(thread) 来挂起/唤醒线程

park():当前线程阻塞,等待被唤醒;
unpark(Thread t):唤醒指定线程;
这种控制机制替代了传统的 wait/notify,更灵活、底层、性能好

 

参考:https://juejin.cn/post/7454026458250166272

posted on 2025-08-05 10:41  colorfulworld  阅读(35)  评论(0)    收藏  举报