Java 8+ 中消除伪共享的最佳实践代码
在 Java 8+ 中,消除伪共享的最佳实践是通过使用 @Contended 注解和合理内存布局策略来避免多个线程频繁写入同一缓存行,从而提高并发性能。
下面是从开发实用角度出发,整理的 Java 8 及以上版本下消除伪共享的最佳实践代码与策略:
一、推荐使用方式:@Contended 注解(Java 8+)
@Contended 是 Java 8 新增的注解(位于 jdk.internal.vm.annotation 包),用于自动为变量填充空白,避免与其他变量共享缓存行。
示例:消除伪共享的计数器类
import jdk.internal.vm.annotation.Contended;
public class CounterWithContended {
@Contended
public volatile long value = 0L;
}
使用前提:必须开启 JVM 参数
@Contended 默认被 JVM 限制使用,必须使用参数显式开启:
-XX:-RestrictContended
🔔 否则注解不会生效,字段不会填充缓存行对齐。
二、实战最佳实践代码:多线程安全计数器
实战案例:并发计数器数组
import jdk.internal.vm.annotation.Contended;
public class ContendedCounterArray {
static final int SIZE = 4;
static class Cell {
@Contended
public volatile long value = 0L;
}
private final Cell[] counters = new Cell[SIZE];
public ContendedCounterArray() {
for (int i = 0; i < SIZE; i++) {
counters[i] = new Cell();
}
}
public void increment(int index) {
counters[index].value++;
}
public long sum() {
long total = 0;
for (Cell cell : counters) {
total += cell.value;
}
return total;
}
}
三、推荐构建方式:开启 @Contended + 设置模块导出
Maven 或 Gradle 启动参数:
--add-exports java.base/jdk.internal.vm.annotation=ALL-UNNAMED
-XX:-RestrictContended
也可以写入 Maven exec-maven-plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>your.main.Class</mainClass>
<arguments>
<argument>-XX:-RestrictContended</argument>
<argument>--add-exports</argument>
<argument>java.base/jdk.internal.vm.annotation=ALL-UNNAMED</argument>
</arguments>
</configuration>
</plugin>
四、最佳实践建议总结
| 项目建议项 | 推荐配置 / 做法 |
|---|---|
| 避免伪共享的首选方案 | 使用 @Contended 注解 |
| 是否要开启 JVM 参数 | 是,必须 -XX:-RestrictContended |
| 建议使用位置 | volatile 变量、统计字段、热点并发计数器 |
| 是否推荐手动 padding | 不推荐(容易出错、难维护) |
| 是否适合所有场景 | 适合高并发写操作场景,不适用于频繁读场景 |
五、推荐替代类:LongAdder 和 LongAccumulator
如果你只想要线程安全的高性能加法,建议直接使用:
LongAdder adder = new LongAdder();
adder.increment(); // 高性能
long total = adder.sum();
它内部使用了分段 + padding,自动避免伪共享,无需手动处理。
六、官方参考资料与链接
- 🔗 JEP 142: Eliminate False Sharing with @Contended
- 📘 OpenJDK @Contended 源码与文档
- 🧪 OpenJDK LongAdder 源码
- 🛠️ Martin Thompson 博客 False Sharing 实测
七、一句话总结
在 Java 8+ 中,使用
@Contended注解 + 启用 JVM 参数-XX:-RestrictContended是消除伪共享最优雅且官方支持的方式,推荐用于高并发写操作、计数器、线程热点字段中,有效提升性能,避免缓存一致性开销。
更多详细内容请关注其他相关文章!