温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java Atomic与锁的性能对比

发布时间:2026-01-07 00:35:35 来源:亿速云 阅读:103 作者:小樊 栏目:编程语言

Java Atomic 与锁的性能对比

结论概览

  • 低到中等竞争、操作粒度很细(如单变量自增、状态翻转)的场景,Atomic 类(CAS)通常比synchronized/ReentrantLock更快,因为它们避免了线程阻塞与上下文切换,属于无锁/乐观并发
  • 高竞争下,CAS 会频繁失败并重试,导致CPU 占用升高、吞吐下降;此时(阻塞式)往往更稳定,或通过LongAdder等“分段累加”方案把热点分散,吞吐可显著优于 AtomicLong。
  • 单线程或几乎无竞争时,两者的额外开销都很小,性能差异通常不明显;随着线程数增加,Atomic 在中等竞争下仍具优势,但竞争极强时可能劣化。
  • 对于复合操作(涉及多个变量/条件判断/等待通知),锁/并发容器更合适;Atomic 仅能保证单个变量的原子性

原理与开销差异

  • Atomic 类基于CAS(Compare-And-Swap)硬件指令实现:线程读取-计算-尝试更新,失败则自旋重试;JVM 会将 CAS 内联为 CPU 指令(如 x86 的LOCK CMPXCHG、ARM 的LDREX/STREX),在用户态完成,不涉及系统调用与线程挂起。JDK 8 多基于sun.misc.Unsafe,JDK 9+ 迁移到VarHandle,语义一致但更安全、可维护。
  • 锁(如synchronized/ReentrantLock)属于悲观并发:竞争时线程可能阻塞/挂起并发生上下文切换,带来调度与同步开销;但阻塞能避免持续自旋的 CPU 浪费,在高竞争下吞吐可能更稳定。

典型场景与推荐选择

场景 更优选择 说明
简单计数/状态位(如请求计数、开关) AtomicInteger/AtomicBoolean 低竞争下吞吐高、代码简洁;避免阻塞与切换
高并发计数(热点累加) LongAdder/DoubleAdder 分段累加降低热点争用,吞吐通常远高于 AtomicLong
复合操作/多变量一致性 synchronized/ReentrantLock 或并发容器 原子类仅保单变量;锁可一次性保护多步逻辑
需要可中断/超时/公平 ReentrantLock 提供 tryLock、lockInterruptibly、公平/非公平选项
读多写少 ReadWriteLock/StampedLock 读写分离提升并发;StampedLock 提供乐观读更高效
存在 ABA 风险 AtomicStampedReference/AtomicMarkableReference 通过版本戳/标记位解决 ABA

性能影响因素与优化要点

  • 竞争强度与重试成本:CAS 在高竞争下失败重试增多,CPU 占用上升;可通过降低共享热点粒度改用 LongAdder、或退化为锁来稳态化吞吐。
  • 伪共享(False Sharing):多个原子变量位于同一缓存行(通常 64 字节)会相互失效,降低性能;可通过字段填充/缓存行对齐或将热点变量拆分到不同对象/数组来规避。
  • 可见性与顺序:volatile仅保证可见性与有序性,不保证复合操作原子性;需要原子性请选择Atomic/锁
  • 公平性需求:锁可实现公平/非公平策略;无锁算法不保证线程调度公平,可能出现个别线程长时间未成功。
  • 版本控制:存在ABA风险的场景使用AtomicStampedReference等带版本机制的类型。

快速自测思路

  • 基准测试建议:固定JDK 版本与硬件,分别测量单线程/多线程(逐步增加线程数)下的吞吐(ops/s)与P95/P99 延迟;对比AtomicInteger vs synchronized、以及AtomicLong vs LongAdder
  • 典型现象:低竞争下 Atomic 往往更快;线程数升高后 Atomic 仍佳,但在极强竞争下可能劣于锁;LongAdder在高并发计数下通常显著优于 AtomicLong。
  • 注意要点:预热 JVM、避免编译期优化干扰、控制变量布局避免伪共享、确保测试逻辑与真实业务一致(例如是否包含 I/O、是否跨线程通信)。
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI