什么是AQS ?

AQS( AbstractQueuedSynchronizer 类 ) 是 一 个 用 来 构 建 锁 和 同 步 器
的 框 架 , 各 种  Lock  包 中 的 锁 ( 常 用 的 有  ReentrantLock、
ReadWriteLock) , 以 及 其 他 如  Semaphore、 CountDownLatch, 甚
至 是 早 期 的 FutureTask 等 , 都 是 基 于 AQS 来 构 建 。
1.  AQS 在 内 部 定 义 了 一 个 volatile int state 变 量 , 表 示 同 步 状 态 : 当 线
程 调 用 lock 方 法 时 , 如 果 state=0, 说 明 没 有 任 何 线 程 占 有 共 享 资 源
的 锁 , 可 以 获 得 锁 并 将 state=1; 如 果 state=1, 则 说 明 有 线 程 目 前 正 在
使 用 共 享 变 量 , 其 他 线 程 必 须 加 入 同 步 队 列 进 行 等 待 。
2.  AQS 通 过 Node 内 部 类 构 成 的 一 个 双 向 链 表 结 构 的 同 步 队 列 , 来 完 成 线
程 获 取 锁 的 排 队 工 作 , 当 有 线 程 获 取 锁 失 败 后 , 就 被 添 加 到 队 列 末 尾 。
o Node  类 是 对 要 访 问 同 步 代 码 的 线 程 的 封 装 , 包 含 了 线 程 本 身 及 其 状 态 叫
waitStatus( 有 五 种 不 同  取 值 , 分 别 表 示 是 否 被 阻 塞 , 是 否 等 待 唤 醒 ,
是 否 已 经 被 取 消 等 ) , 每 个 Node 结 点 关 联 其 prev 结 点 和 next 结
点 , 方 便 线 程 释 放 锁 后 快 速 唤 醒 下 一 个 在 等 待 的 线 程 , 是 一 个 FIFO 的 过
程 。
o Node 类 有 两 个 常 量 , SHARED 和 EXCLUSIVE, 分 别 代 表 共 享 模 式 和 独
占 模 式 。 所 谓 共 享 模 式 是 一 个 锁 允 许 多 条 线 程 同 时 操 作 ( 信 号 量
Semaphore 就 是 基 于 AQS 的 共 享 模 式 实 现 的 ) , 独 占 模 式 是 同 一 个 时
间 段 只 能 有 一 个 线 程 对 共 享 资 源 进 行 操 作 , 多 余 的 请 求 线 程 需 要 排 队 等 待
( 如 ReentranLock) 。
3.  AQS  通 过 内 部 类  ConditionObject  构 建 等 待 队 列 ( 可 有 多 个 ) , 当
Condition  调 用  wait()  方 法 后 , 线 程 将 会 加 入 等 待 队 列 中 , 而 当
Condition 调 用 signal() 方 法 后 , 线 程 将 从 等 待 队 列 转 移 动 同 步 队 列 中
进 行 锁 竞 争 。
4.  AQS  和  Condition  各 自 维 护 了 不 同 的 队 列 , 在 使 用  Lock  和
Condition 的 时 候 , 其 实 就 是 两 个 队 列 的 互 相 移 动 。
问 题 三 : 请 尽 可 能 详 尽 地 对 比 下  Synchronized  和  ReentrantLock
的 异 同 。
ReentrantLock 是 Lock 的 实 现 类 , 是 一 个 互 斥 的 同 步 锁 。
从 功 能 角 度 , ReentrantLock  比  Synchronized  的 同 步 操 作 更 精 细
( 因 为 可 以 像 普 通 对 象 一 样 使 用 ) , 甚 至 实 现  Synchronized  没 有 的
高 级 功 能 , 如 :
 等 待 可 中 断 : 当 持 有 锁 的 线 程 长 期 不 释 放 锁 的 时 候 , 正 在 等 待 的 线 程 可
以 选 择 放 弃 等 待 , 对 处 理 执 行 时 间 非 常 长 的 同 步 块 很 有 用 。
 带 超 时 的 获 取 锁 尝 试 : 在 指 定 的 时 间 范 围 内 获 取 锁 , 如 果 时 间 到 了 仍 然
无 法 获 取 则 返 回 。
 可 以 判 断 是 否 有 线 程 在 排 队 等 待 获 取 锁 。
 可 以 响 应 中 断 请 求 : 与  Synchronized  不 同 , 当 获 取 到 锁 的 线 程 被 中
断 时 , 能 够 响 应 中 断 , 中 断 异 常 将 会 被 抛 出 , 同 时 锁 会 被 释 放 。
 可 以 实 现 公 平 锁 。
从 锁 释 放 角 度 , Synchronized 在 JVM 层 面 上 实 现 的 , 不 但 可 以 通 过
一 些 监 控 工 具 监 控  Synchronized  的 锁 定 , 而 且 在 代 码 执 行 出 现 异 常
时 , JVM 会 自 动 释 放 锁 定 ; 但 是 使 用 Lock 则 不 行 , Lock 是 通 过 代
码 实 现 的 , 要 保 证 锁 定 一 定 会 被 释 放 , 就 必 须 将  unLock()  放 到
finally{} 中 。
从 性 能 角 度 , Synchronized  早 期 实 现 比 较 低 效 , 对 比
ReentrantLock, 大 多 数 场 景 性 能 都 相 差 较 大 。
但 是 在  Java  6  中 对 其 进 行 了 非 常 多 的 改 进 , 在 竞 争 不 激 烈 时 ,
Synchronized  的 性 能 要 优 于  ReetrantLock; 在 高 竞 争 情 况 下 ,
Synchronized 的 性 能 会 下 降 几 十 倍 , 但 是 ReetrantLock 的 性 能 能 维
持 常 态 。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章