validate返回false说明乐观读期间发生过写操作,数据一致性无法保证,必须重试或降级为悲观锁;标准流程是乐观读→读变量→立即validate→失败则用readlock()/writelock()重读并执行逻辑。

StampedLock 的锁转换(如从乐观读转为悲观写)过程中,validate 失败是正常现象,它表示在乐观读期间数据已被修改,原有快照失效。此时不能直接继续操作,必须进入重试循环,重新获取状态并决定后续策略。
validate 失败意味着什么
validate(long stamp) 返回 false 说明:在调用 tryOptimisticRead() 获取戳记后、到调用 validate() 这段时间内,至少发生过一次写操作(无论是否已释放写锁)。这不表示锁被“抢占”,而是乐观读的无锁假设被打破——数据一致性无法保证,必须降级处理。
标准重试循环结构
典型模式是“乐观读 → 验证 → 失败则升级为读锁/写锁 → 执行业务逻辑”。关键在于把验证失败后的锁获取和业务逻辑重放包裹在同一循环中:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 先调用
tryOptimisticRead()获取初始戳记 - 读取共享变量(不加锁,但需确保是普通字段或 volatile 字段)
- 立即调用
validate(stamp)判断是否仍有效 - 若
validate返回true,直接返回结果 - 若返回
false,用readLock()或writeLock()获取悲观锁,再重读数据并执行逻辑,最后解锁
写锁转换时的 validate 与 stamp 更新
从乐观读转写锁需特别注意:不能复用原乐观戳记调用 writeLock()(会抛 IllegalMonitorStateException)。正确流程是:
- 验证失败后,先调用
writeLock()获取新戳记 - 此时必须重新读取所有依赖数据(因为中间可能已变更)
- 完成修改后,用该新戳记调用
unlockWrite(stamp) - 切勿尝试用旧乐观戳记做任何 unlock 操作
避免常见陷阱
常见错误包括:在 validate 前执行耗时计算、验证后未重读数据就直接使用旧值、在循环中重复调用 tryOptimisticRead() 却忽略 stamp 变化。安全做法是:
- 验证前只做轻量读取,不包含分支逻辑或副作用
- 每次进入循环体都视为“全新起点”,所有依赖数据都应重读
- 写锁获取后,务必检查业务前置条件是否仍满足(例如余额是否充足),防止 ABA 类问题
- 必要时配合
isWriteLocked()或getReadLockCount()辅助诊断,但不可用于控制流程
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










