Java 8+ 中消除伪共享的最佳实践代码
                           
天天向上
发布: 2025-07-13 12:01:38

原创
470 人浏览过

在 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不推荐(容易出错、难维护)
是否适合所有场景适合高并发写操作场景,不适用于频繁读场景

五、推荐替代类:LongAdderLongAccumulator

如果你只想要线程安全的高性能加法,建议直接使用:

LongAdder adder = new LongAdder();
adder.increment(); // 高性能
long total = adder.sum();

它内部使用了分段 + padding,自动避免伪共享,无需手动处理。


六、官方参考资料与链接


七、一句话总结

在 Java 8+ 中,使用 @Contended 注解 + 启用 JVM 参数 -XX:-RestrictContended 是消除伪共享最优雅且官方支持的方式,推荐用于高并发写操作、计数器、线程热点字段中,有效提升性能,避免缓存一致性开销。


更多详细内容请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *