701. 请 谈 谈 ReadWriteLock 和 StampedLock。

虽 然 ReentrantLock 和 Synchronized 简 单 实 用 , 但 是 行 为 上 有 一 定 局 限 性 , 要 么 不 占 , 要 么 独 占 。 实 际 应 用 场 景 中 , 有 时 候 不 需 要 大 量 竞 争 的 写 操 作 , 而 是 以 并 发 读 取 为 主 , 为 了 进 一 步 优 化 并 发 操 作 的 粒 度 , Java 提 供 了 读 写 锁 。

读 写 锁 基 于 的 原 理 是 多 个 读 操 作 不 需 要 互 斥 , 如 果 读 锁 试 图 锁 定 时 , 写锁 是 被 某 个 线 程 持 有 , 读 锁 将 无 法 获 得 , 而 只 好 等 待 对 方 操 作 结 束 , 这样 就 可 以 自 动 保 证 不 会 读 取 到 有 争 议 的 数 据 。

ReadWriteLock 代 表 了 一 对 锁 , 下 面 是 一 个 基 于 读 写 锁 实 现 的 数 据 结 构 , 当 数 据 量 较 大 , 并 发 读 多 、 并 发 写 少 的 时 候 , 能 够 比 纯 同 步 版 本 凸 显 出 优 势 :

读 写 锁 看 起 来 比 Synchronized 的 粒 度 似 乎 细 一 些 , 但 在 实 际 应 用 中 , 其 表 现 也 并 不 尽 如 人 意 , 主 要 还 是 因 为 相 对 比 较 大 的 开 销 。

所 以 , JDK 在 后 期 引 入 了 StampedLock, 在 提 供 类 似 读 写 锁 的 同 时 ,还 支 持 优 化 读 模 式 。 优 化 读 基 于 假 设 , 大 多 数 情 况 下 读 操 作 并 不 会 和 写 操 作 冲 突 , 其 逻 辑 是 先 试 着 修 改 , 然 后 通 过 validate 方 法 确 认 是 否 进 入 了 写 模 式 , 如 果 没 有 进 入 , 就 成 功 避 免 了 开 销 ; 如 果 进 入 , 则 尝 试 获 取 读 锁