验证CAS乐观锁正确性的核心方法是:用CountDownLatch同步多线程起点确保并发竞争,以AtomicInteger模拟原子计数器场景,N线程争抢将0设为1,断言仅1次成功且终值为1,同时统计失败次数验证竞争真实性。

直接用多线程并发调用 CAS 操作,配合 CountDownLatch 控制时序、AtomicInteger 统计实际执行次数,并断言最终结果是否符合预期——这是验证 CAS 乐观锁正确性的核心方法。
用 CountDownLatch 同步多个线程的执行起点
避免线程启动时间差导致竞争不可控。让所有线程就绪后“同时”开始执行 CAS 操作:
- 初始化
CountDownLatch startLatch = new CountDownLatch(1)和CountDownLatch endLatch = new CountDownLatch(threadCount) - 每个线程先 await
startLatch,收到信号后再执行 CAS 逻辑,完成后 countDownendLatch - 主线程调用
startLatch.countDown()触发所有线程开跑
设计可验证的 CAS 场景(推荐原子计数器)
以 AtomicInteger 或自定义 CAS 类(如带 compareAndSet 的计数器)为例,目标是:N 个线程各尝试将值从 0 增加到 1,但只允许一个成功:
- 初始值设为 0
- 每个线程循环执行
compareAndSet(0, 1),成功则记录一次(可用AtomicInteger successCount) - 最终断言
successCount.get() == 1且目标变量值为 1
捕获并检查中间状态变化(可选但推荐)
CAS 失败本身是正常行为,需确认失败是否源于真实竞争而非逻辑错误:
立即学习“Java免费学习笔记(深入)”;
- 在 CAS 循环中加入日志或计数器,统计失败次数
- 例如:用
AtomicInteger failureCount在!casResult时递增 - 断言
failureCount.get() == threadCount - 1(若仅允许一次成功)
避免常见陷阱
单元测试不是压力测试,重点是逻辑确定性:
- 不要用
Thread.sleep()控制时序——精度低、不稳定 - 不要依赖“大概率出现竞争”——必须强制制造竞争(靠
CountDownLatch) - 测试类字段不要复用(如共享的
AtomicInteger实例),确保每次测试干净隔离 - JVM 可能优化空循环,CAS 失败后建议加轻量级退避(如
Thread.onSpinWait(),Java 9+)或简单Thread.yield()
不复杂但容易忽略的是同步起点和结果可断言性——只要线程真正并发执行 CAS,且最终状态满足线性一致性预期,测试就立得住。


















