当前位置: 首页 > news >正文

JUC包里的同步组件主要实现了AQS的哪些主要方法

要理解 JUC(java.util.concurrent)包中同步组件的底层逻辑,核心是它们都基于AbstractQueuedSynchronizer(AQS)框架——AQS 提供了通用的同步状态管理、CLH 队列(等待队列)和模板方法,而具体组件只需重写 AQS 的关键抽象方法,即可实现自定义的同步语义。

一、先明确 AQS 的核心角色

AQS 是一个抽象基类,定义了同步组件的通用结构:

  • 同步状态(state:用 volatile int表示同步状态(如锁的重入次数、计数器的剩余值)。
  • CLH 队列:双向链表实现的等待队列,存储未获取到同步状态的线程。
  • 节点状态(waitStatus:表示节点的等待状态(如 CANCELLEDSIGNALCONDITION等)。
  • 模板方法:如 acquire(int arg)(独占获取)、release(int arg)(独占释放)、acquireShared(int arg)(共享获取)、releaseShared(int arg)(共享释放)——这些方法调用需要子类重写的抽象方法完成具体逻辑。

二、JUC 组件重写的 AQS 核心方法

不同 JUC 组件(如锁、计数器、信号量)对应独占模式共享模式,因此重写的 AQS 方法也不同。以下是典型组件的实现分析:

1. 独占模式组件(如 ReentrantLockThreadPoolExecutor.Worker

独占模式用于“一次只有一个线程持有资源”的场景,需重写:

  • tryAcquire(int arg):尝试获取独占同步状态(成功返回 true,失败返回 false)。
  • tryRelease(int arg):尝试释放独占同步状态(成功返回 true,失败返回 false)。
  • isHeldExclusively():判断当前线程是否独占同步状态(用于条件变量)。
示例 1:ReentrantLock(可重入独占锁)

ReentrantLock内部通过 Sync抽象类继承 AQS,再派生出 NonfairSync(非公平锁)和 FairSync(公平锁),重写以下方法:

  • tryAcquire(int acquires)

    尝试获取锁(acquires=1表示获取一次锁)。

    • 非公平锁:直接通过 CAS 修改 state(若 state==0则获取成功,否则判断是否是当前线程重入)。
    • 公平锁:先检查 CLH 队列中是否有前驱节点(保证先到先得),再尝试 CAS 修改 state
    // NonfairSync 的 tryAcquire
    protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) { // CAS 抢锁setExclusiveOwnerThread(current);return true;}} else if (current == getExclusiveOwnerThread()) { // 重入int nextc = c + acquires;if (nextc < 0) throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;
    }
  • tryRelease(int releases)

    释放锁(releases=1表示释放一次)。减少 state,若 state变为 0,则彻底释放锁,并设置 exclusiveOwnerThread为 null

    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;
    }
  • isHeldExclusively():判断当前线程是否持有锁(用于 Condition的等待队列)。
示例 2:ThreadPoolExecutor.Worker(工作线程的独占锁)

Worker继承 AbstractQueuedLongSynchronizer(AQS 的长整型版本),用于实现不可重入的独占锁

  • tryAcquire(long arg):只有当前线程是 Worker自身时才能获取锁(防止并发修改任务)。
  • tryRelease(long arg):释放锁(将 state置 0)。
2. 共享模式组件(如 CountDownLatchSemaphoreCyclicBarrier

共享模式用于“多个线程可同时持有资源”的场景,需重写:

  • tryAcquireShared(int arg):尝试获取共享同步状态(返回 >=0表示成功,<0表示失败)。
  • tryReleaseShared(int arg):尝试释放共享同步状态(成功返回 true,失败返回 false)。
  • getSharedQueuedThreads()(可选):获取等待队列中的共享线程(用于监控)。
示例 1:CountDownLatch(闭锁)

CountDownLatch内部通过 Sync继承 AQS,state初始化为计数器 count

  • tryAcquireShared(int acquires)

    尝试获取共享锁(即判断计数器是否为 0)。若 state == 0,返回 1(成功);否则返回 -1(失败,进入等待队列)。

    protected int tryAcquireShared(int acquires) {return (getState() == 0) ? 1 : -1;
    }
  • tryReleaseShared(int releases)

    释放共享锁(减少计数器)。通过 CAS 循环将 state减 1,若 state变为 0,则唤醒所有等待的共享线程。

    protected boolean tryReleaseShared(int releases) {for (;;) {int c = getState();if (c == 0) return false; // 已经是 0,无需释放int nextc = c - 1;if (compareAndSetState(c, nextc))return nextc == 0; // 若减到 0,返回 true 唤醒其他线程}
    }
示例 2:Semaphore(信号量)

Semaphore内部通过 Sync继承 AQS,state表示可用许可数:

  • tryAcquireShared(int acquires)

    尝试获取 acquires个许可(若剩余许可足够,则 CAS 减少许可并返回成功;否则失败)。

    protected int tryAcquireShared(int acquires) {for (;;) {int available = getState();int remaining = available - acquires;if (remaining < 0 || compareAndSetState(available, remaining))return remaining;}
    }
  • tryReleaseShared(int releases)

    释放 releases个许可(CAS 增加许可,若成功则唤醒等待线程)。

3. 双模式组件(如 ReentrantReadWriteLock

ReentrantReadWriteLock同时支持读锁(共享)写锁(独占),内部通过两个 Sync子类实现:

  • 写锁(WriteLock:继承 Sync,重写 tryAcquire和 tryRelease(独占逻辑)。
    • tryAcquire:判断是否有其他线程持有写锁,或当前线程是否可重入。
  • 读锁(ReadLock:继承 Sync,重写 tryAcquireShared和 tryReleaseShared(共享逻辑)。
    • tryAcquireShared:判断是否有写锁持有,或当前线程是否已持有读锁(可重入)。
4. 条件变量(ConditionObject

ConditionObject是 AQS 的内部类,实现 Condition接口,依赖 AQS 的条件队列(单向链表):

  • await():释放当前线程的同步状态,将节点从同步队列移到条件队列,进入等待。
  • signal():将条件队列中的第一个节点移回同步队列,唤醒该线程。
  • signalAll():将条件队列中的所有节点移回同步队列,唤醒所有线程。

三、总结:JUC 组件与 AQS 方法的对应关系

组件类型

典型组件

模式

重写的 AQS 核心方法

独占锁

ReentrantLock

独占

tryAcquiretryReleaseisHeldExclusively

独占锁

ThreadPoolExecutor.Worker

独占

tryAcquiretryRelease

共享锁

CountDownLatch

共享

tryAcquireSharedtryReleaseShared

共享锁

Semaphore

共享

tryAcquireSharedtryReleaseShared

双模式锁

ReentrantReadWriteLock

独占+共享

写锁:tryAcquiretryRelease;读锁:tryAcquireSharedtryReleaseShared

条件变量

ConditionObject

——

依赖 AQS 的条件队列实现

四、关键结论

JUC 组件的底层逻辑可总结为:

AQS 提供通用框架(状态管理、队列、模板方法),具体组件通过重写 tryAcquire/tryRelease(独占)或 tryAcquireShared/tryReleaseShared(共享)实现自定义同步语义

这种设计让 JUC 组件无需重复造轮子,只需聚焦于“如何获取/释放同步状态”,即可快速实现高效、可靠的同步工具。

http://www.dtcms.com/a/610108.html

相关文章:

  • wordpress公司展示网站模板网站推广需要多少钱易下拉系统
  • wordpress站点费用网站底部的图标
  • 引力本体的几何之歌:从星体永恒吸引到人工场操控时空的范式革命
  • Docker-Android容器化开发:如何通过Cpolar实现远程环境无缝协作
  • ## 2.2 状态同步
  • 翻译技巧英语
  • 11.14 脚本网页 迷宫逃离
  • 手机网站开发成appWordPress博客建站系统
  • 定义舱驾一体新架构:黑芝麻智能武当C1200家族如何成为跨域计算“第一芯”
  • 小白建站东莞网络营销公司
  • SImpack轨道车辆建模练习
  • react项目创建从0到1及安装(ts、axios、路由、redux)
  • 网站怎么做动态背景图片做网站需要准备哪些材料
  • 网站建设分哪几个版块关键词没有排名的网站怎么做
  • 什么是关键字驱动测试(Keyword-Driven Testing)?
  • 颠覆叙事:Google Veo 3.1与Flow如何开启连贯AI动画长视频时代
  • 【运维】Nginx 入门笔记
  • Docker 部署 GitLab 和 GitLab Runner 指南
  • RabbitMQ 跨平台安装与基础使用指南(Windows_macOS_Ubuntu_Docker 全场景)
  • 市城乡规划建设局网站seo搜索引擎优化内容
  • 2025_11_14洛谷【入门1】数据结构刷题小结
  • wordpress打赏链接网站建设 小影seo
  • 哪个网站能学做微商上海建设网站是多少
  • 第34节:反向运动学与角色动画自然化
  • Virtual Ontology:基于语义层的自然语言SQL生成系统技术深度解析
  • Django过时了吗?从ASGI到AI时代的思考
  • 网站建设需求和页面需求怎么提5m带宽做视频网站
  • 图论专题(六):“隐式图”的登场!DFS/BFS 攻克「岛屿数量」
  • 当Rokid遇见BOLON,科技与时尚的这次握手重新定义“眼镜”
  • 图论专题(五):图遍历的“终极考验”——深度「克隆图」