首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >AbstractQueuedSynchronizer

AbstractQueuedSynchronizer

原创
作者头像
兰亭集
发布2026-04-26 10:32:46
发布2026-04-26 10:32:46
150
举报
文章被收录于专栏:软件工程软件工程

状态流转

AbstractQueuedSynchronizer

几个主要属性:

  • exclusiveOwnerThread:持有当前锁的线程
  • state:加锁状态,是个int值,通过判断和维护此状态实现锁互斥逻辑和锁重入状态
  • head,tail:等待锁的线程队列sync queue

acquire方法获取锁

从ReentrantLock FairSync加锁一步步理解acquire方法的实现,

代码语言:java
复制
// ReentrantLock.FairSync.lock()
public void lock() {
    sync.lock();
}

// ReentrantLock.Sync.lock()
final void lock() {
    if (!initialTryLock())
        acquire(1);  // AbstractQueuedSynchronizer.acquire()
}

// ReentrantLock.FairSync.initialTryLock()
final boolean initialTryLock() {
    Thread current = Thread.currentThread();
    int c = getState();  // 当前加锁状态
    if (c == 0) {  // 未加锁
        if (!hasQueuedThreads() && compareAndSetState(0, 1)) {  // 尝试CAS加锁,因为是公平锁,
            setExclusiveOwnerThread(current);  // 设置锁owner
            return true;  // 加锁成功
        }
    } else if (getExclusiveOwnerThread() == current) {  // 如果当前线程已经持有该锁
        if (++c < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(c);  // 锁重入次数+1
        return true;  // 加锁成功
    }
    return false;    // 加锁失败
}

// AbstractQueuedSynchronizer.acquire()
public final void acquire(int arg) {
    if (!tryAcquire(arg))  // 子类需实现tryAcquire方法尝试获取锁
        acquire(null, arg, false, false, false, 0L);  // 加锁及等待锁逻辑
}

// ReentrantLock.FairSync.tryAcquire()
protected final boolean tryAcquire(int acquires) {
    if (getState() == 0 && !hasQueuedPredecessors() &&
        compareAndSetState(0, acquires)) {  // sync queue中无等待锁的线程,且加锁成功
        setExclusiveOwnerThread(Thread.currentThread());  // 设置锁owner为当前线程
        return true;  // 加锁成功
    }
    return false;  // 加锁失败
}

// AbstractQueuedSynchronizer.acquire()
final int acquire(Node node, int arg, boolean shared,
                      boolean interruptible, boolean timed, long time) {
    /**
     * 不断尝试获取锁,
     * 当sync queue不为空时,把当前线程加入sync queue队尾,
     * 当前线程排在sync queue队首时,调用tryAcquire尝试加锁,
     * 当前线程不在sync queue的队首或加锁失败,则当前线程进入睡眠状态(LockSupport.park方法),
     * 其他线程释放锁后会激活sync queue的队首线程(LockSupport.unpark方法),当前线程成为队首线程并被激活后,会继续尝试加锁直到加锁成功,
     * 加锁成功后从sync queue队首移除当前线程
    */
    ...
}

release方法释放锁

同样从ReentrantLock FairSync释放锁一步步理解release方法的实现,

代码语言:java
复制
// ReentrantLock.FairSync.unlock()
public void unlock() {
    sync.release(1);
}

// ReentrantLock.Sync.release()
public final boolean release(int arg) {
    if (tryRelease(arg)) {  // AbstractQueuedSynchronized的子类需实现tryRelease方法尝试释放锁
        signalNext(head);  // 激活睡眠状态下的sync queue队首线程
        return true;  // 释放锁成功
    }
    return false;  // 释放锁失败
}

// ReentrantLock.Sync.tryRelease()
protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (getExclusiveOwnerThread() != Thread.currentThread())  // 线程owner必需是当前线程
        throw new IllegalMonitorStateException();
    boolean free = (c == 0);
    if (free)  // 锁完全释放
        setExclusiveOwnerThread(null);
    setState(c);
    return free;
}

Condition

主要属性:

  • firstWaiter,lastWaiter:线程等待队列wait queue
    • 调用Condition.await方法的线程会进入此队列,然后线程会释放持有的锁,再调用LockSupport.park方法进入等待状态
    • 调用Condition.signal方法会把线程从wait queue队列移到sync queue中,线程重新获取锁后继续原逻辑的执行

await方法等待

代码语言:java
复制
// AbstractQueuedSynchronizer.ConditionObject.await()
public final void await() throws InterruptedException {
    ...
    ConditionNode node = newConditionNode();  // 创建等待节点
    if (node == null)
        return;
    int savedState = enableWait(node);  // 添加到wait queue中,释放持有的锁
    ...
    while (!canReacquire(node)) {  // 当前线程是否从wait queue移到sync queue中
        ...
                    ForkJoinPool.managedBlock(node);  // LockSupport.park线程进入等待状态
        ...
    
    }
    ...
    acquire(node, savedState, false, false, false, 0L);  // 线程在sync queue中,尝试获取曾经释放的锁
    ...
}

// ReentrantLock.FairSync.enableWait()
private int enableWait(ConditionNode node) {
    if (isHeldExclusively()) {
        node.waiter = Thread.currentThread();
        node.setStatusRelaxed(COND | WAITING);
        ConditionNode last = lastWaiter;
        if (last == null)
            firstWaiter = node;
        else
            last.nextWaiter = node;
        lastWaiter = node;  // 加入到wait queue中
        int savedState = getState();
        if (release(savedState))  // 释放持有的所有锁
            return savedState;
    }
    node.status = CANCELLED; // lock not held or inconsistent
    throw new IllegalMonitorStateException();
}

signal方法通知

代码语言:java
复制
// ReentrantLock.FairSync.signal()
public final void signal() {
    ConditionNode first = firstWaiter;
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    else if (first != null)
        doSignal(first, false);
}

// ReentrantLock.FairSync.doSignal()
private void doSignal(ConditionNode first, boolean all) {
    while (first != null) {
        ConditionNode next = first.nextWaiter;

        if ((firstWaiter = next) == null)  // 从wait queue中移除
            lastWaiter = null;
        else
            first.nextWaiter = null;

        if ((first.getAndUnsetStatus(COND) & COND) != 0) {
            enqueue(first);  // 加入到sync queue中
            if (!all)
                break;
        }

        first = next;
    }
}

一些AbstractQueuedSynchronizer的实现类

  • Semaphore:信号量,用于控制并发线程的数量。
  • CountDownLatch:倒计数器,一个或多个线程需要等待一定数量的条件满足后才能继续执行,满足条件的逻辑在其他线程中完成。
  • ReadWriteLock:读写锁,读锁与读锁不互斥,读锁与写锁、写锁与写锁都互斥,适用于读多写少的场景。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 状态流转
  • AbstractQueuedSynchronizer
    • acquire方法获取锁
    • release方法释放锁
  • Condition
    • await方法等待
    • signal方法通知
  • 一些AbstractQueuedSynchronizer的实现类
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档