CAS不直接操作数据库字段,而是与数据库版本号字段协同实现乐观锁:CAS管理本地版本号生成与校验,数据库version字段负责行级并发控制,二者分层协作不可替代。

Java 中 CAS 本身不直接操作数据库字段,它作用于内存中的变量(如 AtomicInteger)。要让它配合数据库里的业务版本号字段完成安全更新,关键在于**分层协同**:CAS 管理本地状态或轻量级计数,而版本号机制负责数据库行级并发控制。两者不是替代关系,而是按职责分工协作。
版本号字段是数据库乐观锁的主干
业务表中必须有 version(或 update_time)字段,这是数据库层面检测并发修改的依据:
- 读取数据时,一并查出当前
version值; - 更新时,SQL 显式带上条件:
WHERE id = ? AND version = ?; - 用
JdbcTemplate.update()或 MyBatis 的int affectRows = mapper.update(...)判断是否更新成功(返回值为 0 表示版本不匹配,冲突)。
CAS 可用于支撑版本号的生成与校验逻辑
在需要高并发生成版本号、或校验版本递增合法性的场景下,CAS 能提供无锁保障:
- 用
AtomicInteger currentVersion缓存最新已提交的版本号,避免每次读 DB; - 业务更新前调用
currentVersion.compareAndSet(expected, expected + 1)尝试“预占”下一个版本; - 若 CAS 成功,说明当前线程获得版本号分配权,再带着该版本号发起 DB 更新;
- 若失败,说明其他线程已抢先更新,需重新加载 DB 数据及最新 version 后重试。
典型配合流程(以库存扣减为例)
假设商品表含 stock 和 version 字段:
立即学习“Java免费学习笔记(深入)”;
- 步骤一:查出商品记录,得到
stock=100, version=5; - 步骤二:检查库存充足后,构造更新语句:
UPDATE product SET stock = 99, version = 6 WHERE id = 1 AND version = 5; - 步骤三:执行 SQL,判断影响行数;
- 步骤四:若影响行为 0,说明 version 已变 → 重查最新数据,回到步骤一;
- 步骤五:若需在应用层做版本号自增协调(如分布式多服务共管同一 version 序列),可用
AtomicStampedReference<Integer>防 ABA 问题,把 version 和时间戳/标识绑定校验。
不建议让 CAS 直接替代版本号字段
单纯靠 AtomicInteger 管理数据库记录的 version 是危险的:
- 进程重启后内存 version 丢失,无法与 DB 持久化版本对齐;
- 多个 JVM 实例无法共享同一 CAS 变量,失去一致性;
- DB 事务回滚时,CAS 已递增,但数据库未生效,造成错乱。
所以版本号必须由数据库字段承载,CAS 仅作为应用层辅助工具,用于优化 version 获取路径或增强校验强度。


















