第12章 Java内存模型测试报告
测试时间: 2026-03-29
测试环境: Windows, JDK 17, Maven 3.9+
测试类: com.linsir.abc.core.jvm.jmm.JMMTest
1. 测试概述
本次测试针对Java内存模型(JMM)相关代码进行验证,共执行 12个测试用例,全部通过。
测试范围
- volatile关键字可见性和原子性
- synchronized关键字线程安全性
- 线程状态转换
- happens-before规则
- 并发读写综合场景
2. 测试结果汇总
| 指标 | 数值 |
|---|---|
| 测试用例总数 | 12 |
| 通过 | 12 |
| 失败 | 0 |
| 错误 | 0 |
| 跳过 | 0 |
| 总耗时 | 1.976秒 |
结果: ✅ 全部通过
3. 详细测试结果
3.1 Test volatile flag visibility
- 测试方法:
testVolatileFlag() - 测试内容: 验证volatile状态标志位的可见性
- 执行结果: ✅ 通过
- 关键输出:
Worker-Thread is working... Worker-Thread is working... Worker-Thread stopped. - 验证点: 主线程修改running标志位后,工作线程能够立即看到并停止
3.2 Test volatile singleton DCL
- 测试方法:
testVolatileSingleton() - 测试内容: 验证DCL单例模式的正确性
- 执行结果: ✅ 通过
- 测试参数:
- 线程数: 100
- 验证点: 所有线程获取的实例ID相同
- 验证点: volatile防止指令重排序,确保单例对象正确初始化
3.3 Test volatile does not guarantee atomicity
- 测试方法:
testVolatileNotAtomic() - 测试内容: 验证volatile不能保证复合操作的原子性
- 执行结果: ✅ 通过
- 关键数据:
Expected: 50000 Actual: 49566 (小于期望值) - 验证点: volatile计数器在多线程环境下出现数据竞争,证明volatile不能保证i++的原子性
3.4 Test AtomicInteger atomicity
- 测试方法:
testAtomicCounter() - 测试内容: 验证AtomicInteger的原子性保证
- 执行结果: ✅ 通过
- 关键数据:
Expected: 50000 Actual: 50000 - 验证点: AtomicInteger通过CAS操作保证原子性,结果与期望值一致
3.5 Test synchronized counter
- 测试方法:
testSynchronizedCounter() - 测试内容: 验证synchronized计数器的线程安全性
- 执行结果: ✅ 通过
- 关键数据:
Expected: 50000 Actual: 50000 - 验证点: synchronized保证复合操作的原子性,无并发问题
3.6 Test synchronized memory visibility
- 测试方法:
testSynchronizedVisibility() - 测试内容: 验证synchronized的内存可见性保证
- 执行结果: ✅ 通过
- 关键输出:
Thread-251 wrote: 42 Thread-252 read: 42 - 验证点: 写线程写入42后,读线程能够正确读取到42,证明synchronized保证可见性
3.7 Test thread state transitions
- 测试方法:
testThreadState() - 测试内容: 验证线程状态的正确转换
- 执行结果: ✅ 通过
- 验证状态:
- NEW → RUNNABLE → TIMED_WAITING → TERMINATED
- 验证点: 线程状态转换符合Java线程模型规范
3.8 Test thread implementation methods
- 测试方法:
testThreadImplementation() - 测试内容: 验证3种线程实现方式
- 执行结果: ✅ 通过
- 验证内容:
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口(带返回值)
- 关键输出:
Thread running: Test-Thread-1 Runnable running: Test-Runnable-1 Callable running: Test-Callable-1
3.9 Test happens-before monitor lock rule
- 测试方法:
testHappensBeforeMonitorLock() - 测试内容: 验证happens-before监视器锁规则
- 执行结果: ✅ 通过
- 验证点: unlock操作happens-before后续lock操作,保证可见性
3.10 Test happens-before volatile variable rule
- 测试方法:
testHappensBeforeVolatile() - 测试内容: 验证happens-before volatile变量规则
- 执行结果: ✅ 通过
- 验证点: volatile写happens-before后续volatile读,通过传递性保证前面操作的可见性
3.11 Test ReadWriteCounter performance
- 测试方法:
testReadWriteCounter() - 测试内容: 验证ReadWriteCounter的性能和正确性
- 执行结果: ✅ 通过
- 关键数据:
ReadWriteCounter: 10 readers, 100 reads each, completed in 1ms - 验证点: volatile读操作性能优异,10个线程各读100次仅需1ms
3.12 Test concurrent read and write
- 测试方法:
testConcurrentReadWrite() - 测试内容: 综合并发读写测试
- 执行结果: ✅ 通过
- 测试参数:
- 写线程: 10个,每线程100次自增
- 读线程: 20个,每线程100次读取
- 关键数据:
Expected: 1000 Actual: 1000 - 验证点: 多线程并发读写下,计数器保持数据一致性
4. 关键发现
4.1 volatile vs synchronized/Atomic
| 特性 | volatile | synchronized | AtomicInteger |
|---|---|---|---|
| 可见性 | ✅ 保证 | ✅ 保证 | ✅ 保证 |
| 原子性 | ❌ 不保证复合操作 | ✅ 保证 | ✅ 保证 |
| 性能 | 最优 | 一般 | 较好 |
| 适用场景 | 状态标志位、DCL | 复合操作 | 计数器、累加器 |
4.2 测试数据对比
并发计数测试(50线程 × 1000次):
- volatile: 49566/50000 (99.13%,有数据竞争)
- synchronized: 50000/50000 (100%,线程安全)
- AtomicInteger: 50000/50000 (100%,线程安全)
5. 结论
- volatile 能够保证可见性和有序性,但不能保证复合操作的原子性
- synchronized 能够保证原子性、可见性和有序性,适用于需要互斥的场景
- Atomic类 通过CAS操作提供无锁的原子性保证,性能优于synchronized
- happens-before规则 是判断线程安全的重要依据
- 所有12个测试用例全部通过,代码实现正确
6. 附录
6.1 测试命令
bash
# 运行所有JMM测试
mvn test -Dtest=JMMTest
# 运行单个测试
mvn test -Dtest=JMMTest#testVolatileFlag
# 生成测试报告
mvn test -Dtest=JMMTest -DreportFormat=plain6.2 测试环境信息
Apache Maven 3.9.x
Java version: 17.0.x
OS: Windows 10/11
CPU: Multi-core processor
Memory: 16GB+报告生成时间: 2026-03-29
测试执行状态: ✅ 全部通过