跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

Java 并发性能优化:如何避免伪共享

伪共享是并发编程中常见的性能陷阱,源于多变量占用同一缓存行导致线程间频繁缓存失效。解析其硬件原理,并给出 Java 中使用 @Contended 注解或字节填充的解决方案,帮助开发者优化高并发场景下的系统性能。

疯疯癫癫发布于 2021/7/12更新于 2026/9/2068 浏览
Java 并发性能优化:如何避免伪共享

什么是伪共享?

在并发编程中,我们常听到一个词叫'伪共享'(False Sharing)。听起来有点绕,但实际影响很直接。简单来说,当多个线程同时修改同一个缓存行里的不同变量时,由于 CPU 缓存机制的限制,会导致性能显著下降。

为什么会发生?

CPU 从内存读取数据时,并不是按字节或单个变量进行的,而是以'缓存行'(Cache Line)为单位。通常一行是 64 字节。即使你的代码只访问了其中一个变量,整行数据都会被加载到缓存中。

这就埋下了隐患:如果两个线程分别操作位于同一缓存行的不同变量,虽然逻辑上它们互不干扰,但在硬件层面,它们共享了同一条缓存通道。当一个线程修改了该缓存行,另一个线程的缓存副本就会失效,必须重新从内存或其他核心获取最新数据。这种频繁的缓存一致性校验和同步,就是伪共享带来的性能损耗。

怎么解决?

既然知道了原因,解决方案也就清晰了。核心思路是让这些变量尽可能落在不同的缓存行里。

1. 手动填充(Padding)

这是最底层的做法。在定义变量时,预留足够的空间,确保每个变量占据独立的缓存行。比如,假设缓存行是 64 字节,你可以声明一个数组来填充剩余空间。

public class FalseSharing {
    // 每个 long 占 8 字节,需要填充 7 个 long 才能凑够 64 字节
    public static final int CACHE_LINE_SIZE = 64;
    
    public static class Padding {
        public volatile long p1, p2, p3, p4, p5, p6, p7; // 填充
        public volatile long value; // 实际数据
        public volatile long q1, q2, q3, q4, q5, q6, q7; // 填充
    }
}

这种方式虽然有效,但代码可读性较差,而且依赖具体的架构参数。

2. 使用 @Contended 注解

JDK 8 引入了解决这个问题的利器——@sun.misc.Contended(后来移到了 jdk.internal.misc 包,但在标准库中通常通过 JVM 参数支持)。不过更推荐的方式是使用 @Contended 注解(需配合 -XX:-RestrictContended 等参数,或者直接使用 OpenJDK 提供的实现)。

在实际开发中,如果你使用的是较新的 JDK 版本,可以直接利用 @Contended 让 JVM 自动处理填充。这比手写 padding 要安全得多。

import sun.misc.Contended;

public class OptimizedCounter {
    @Contended
    private volatile long count1;
    
    @Contended
    private volatile long count2;
    
    // 其他业务逻辑...
}

注意:在某些 JVM 实现中,可能需要开启特定参数才能生效,具体视环境而定。但原理是一样的,JVM 会在字段间插入必要的填充字节。

总结

伪共享不是逻辑错误,不会抛出异常,但它会悄悄拖慢你的系统。在高并发、高性能场景下,尤其是涉及大量计数器或状态更新时,务必留意这个问题。优先使用语言层面的注解工具,必要时再考虑底层填充,保持代码的可维护性同样重要。

目录

  1. 什么是伪共享?
  2. 为什么会发生?
  3. 怎么解决?
  4. 1. 手动填充(Padding)
  5. 2. 使用 @Contended 注解
  6. 总结

更多推荐文章

查看全部
  • 基于 AD7606 的 8 通道高速同步采集系统设计与 Verilog 实现
  • Quartus II 13.1 与 ModelSim 安装配置及仿真教程
  • 基于 LlamaFactory 微调 Qwen3.5-4B 模型实战
  • Retriever 不是向量库的糖衣,而是 Eino 的读侧统一协议
  • 大模型私有化部署与精调:面向垂直行业与特定场景
  • Spec Kit:GitHub 官方推出的规范驱动开发工具包
  • Cursor 辅助开发:Web 背单词应用实战指南
  • 2026 年 AI Agent 开发:10 个实战验证的设计模式
  • 网络安全入门常用的学习站点与工具清单
  • C++ 不使用第三方库在 RGB 图像上叠加文字
  • 主流 AIGC 检测降重工具实测对比与避坑指南
  • 渐进式 AIGC 系统架构与多模态大模型集成方案
  • GitHub 学生开发者包认证操作指南
  • Cursor 中 MCP 服务配置与使用指南
  • Neo4j 跨平台安装与基础配置指南(Windows/Mac/Linux)
  • 基于 GFPGAN 的低质量人脸图像超分辨率恢复实战
  • CentOS 部署 Teemii 搭建私人漫画阅读库
  • OpenClaw 文献检索、数据整理与论文排版自动化实战
  • 前端安全:别让你的应用变成黑客的游乐场
  • MS-S1 MAX 与 AI MAX 395 在 Ubuntu 24 使用 Vulkan 版 llama.cpp 运行 gpt-oss 120b

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online