当前位置: 首页 > news >正文

高并发点赞场景Synchronized、AtomicLong、LongAdder 和 LongAccumulator性能分析

在高并发点赞场景中,我们需要一个高效、线程安全的计数器来记录点赞数。synchronized、AtomicLong、LongAdder 和 LongAccumulator 都是 Java 中用于实现原子操作的类,但它们的性能在高并发下差异显著。性能主要取决于线程竞争程度:竞争越高,吞吐量(单位时间处理的操作数)和可扩展性(线程数增加时的性能表现)越关键。下面我将基于高并发点赞案例(如百万级线程同时点赞),逐步分析它们的性能特点和排名。

1. synchronized

  • 原理:使用内置锁(monitor)确保线程安全。每个点赞操作需获取锁,操作完成后释放锁。
  • 性能分析
    • 在高并发下,锁竞争激烈。线程会频繁阻塞和唤醒,导致大量上下文切换开销。
    • 吞吐量低:随着线程数增加,性能急剧下降。例如,在 100 个线程并发时,吞吐量可能降到单线程的 1/10。
    • 延迟高:操作平均耗时长,因为线程需等待锁。
    • 适用场景:低并发或简单同步任务,但不适合高并发点赞。
  • 示例代码(模拟点赞计数器)
    public class LikeCounter {private long count = 0;public synchronized void increment() {count++; // 点赞操作}public long getCount() {return count;}
    }
    

2. AtomicLong

  • 原理:基于 CAS(Compare-And-Swap)操作实现原子性,无需锁。通过硬件指令优化。
  • 性能分析
    • 比 synchronized 更好:CAS 避免了阻塞,减少了上下文切换。
    • 但在高并发下,CAS 失败率高:多个线程竞争同一变量时,需重试多次,导致 CPU 空转和缓存一致性开销。
    • 吞吐量中等:在低到中并发下表现良好,但线程数超过 CPU 核心数时,性能下降明显。例如,在 50 个线程时,吞吐量可能比 LongAdder 低 30-50%。
    • 延迟较低:但高竞争时仍不稳定。
    • 适用场景:中低并发计数器,简单原子操作。
  • 示例代码
    import java.util.concurrent.atomic.AtomicLong;public class LikeCounter {private AtomicLong count = new AtomicLong(0);public void increment() {count.incrementAndGet(); // 原子点赞操作}public long getCount() {return count.get();}
    }
    

3. LongAdder

  • 原理:Java 8 引入,使用分段(cell)机制减少竞争。每个线程操作独立的局部变量,最后通过 sum() 合并结果。
  • 性能分析
    • 高并发下最优:通过分散热点,显著降低竞争。CAS 失败率低,CPU 利用率高。
    • 吞吐量高:线程数增加时,性能可线性扩展。例如,在 100 个线程下,吞吐量可达 AtomicLong 的 2-5 倍。
    • 延迟低:操作平均耗时短,适合高频更新。
    • 缺点:sum() 方法有合并开销,但点赞场景通常读少写多,影响小。
    • 适用场景:高并发计数器如点赞、实时统计。
  • 示例代码
    import java.util.concurrent.atomic.LongAdder;public class LikeCounter {private LongAdder count = new LongAdder();public void increment() {count.increment(); // 高效点赞操作}public long getCount() {return count.sum();}
    }
    

4. LongAccumulator

  • 原理:Java 8 引入,类似 LongAdder,但支持自定义累加函数(如加法、最大值)。内部也使用分段机制。
  • 性能分析
    • 与 LongAdder 相当:在简单加法操作(如点赞的 increment)上,性能几乎相同。分段机制减少竞争。
    • 吞吐量高:可扩展性好,线程数增加时性能稳定。
    • 优势:更灵活,支持复杂操作(如累加器函数),但点赞场景只需简单加 1,因此无额外优势。
    • 延迟低:类似 LongAdder。
    • 适用场景:高并发且需自定义累加逻辑的任务,但点赞场景中性能与 LongAdder 持平。
  • 示例代码
    import java.util.concurrent.atomic.LongAccumulator;
    import java.util.function.LongBinaryOperator;public class LikeCounter {private LongAccumulator count;public LikeCounter() {LongBinaryOperator accumulator = (x, y) -> x + y; // 自定义加法函数count = new LongAccumulator(accumulator, 0);}public void increment() {count.accumulate(1); // 点赞操作}public long getCount() {return count.get();}
    }
    

性能排名分析

在高并发点赞场景(如 100+ 线程同时操作),性能从高到低排名如下:

  1. LongAdder 和 LongAccumulator(并列最佳)
    • 理由:分段机制最小化竞争,吞吐量最高(可达百万级操作/秒),延迟最低。在高线程数下可扩展性最好。
  2. AtomicLong
    • 理由:CAS 优于锁,但高竞争时重试开销导致吞吐量下降,性能次于分段类。
  3. synchronized
    • 理由:锁竞争严重,吞吐量最低(可能低于 10% 的分段类),延迟最高,不适合高并发。
关键性能指标比较(基于基准测试数据)
吞吐量(高并发下)延迟(平均操作耗时)可扩展性(线程增加时)
LongAdder非常高很低优秀
LongAccumulator非常高很低优秀
AtomicLong中等中等一般
synchronized
  • 高并发热点问题:点赞场景是“写密集型”,变量频繁更新。synchronized 和 AtomicLong 在单一变量上竞争激烈,而 LongAdder/LongAccumulator 通过分段分散竞争,减少缓存行冲突(false sharing)。
  • 实际测试数据:在 JMH 基准测试中,线程数 > 32 时,LongAdder 的吞吐量通常比 AtomicLong 高 3-10 倍,比 synchronized 高 10-50 倍。LongAccumulator 在加法操作上与 LongAdder 性能一致。
  • 推荐:对于高并发点赞的功能,优先选择 LongAdder(简单计数)或 LongAccumulator(如果需要灵活性)。避免 synchronized 和 AtomicLong 在高竞争下使用。
http://www.dtcms.com/a/279591.html

相关文章:

  • Linux 系统管理基础教程
  • MyBatis 在执行 SQL 时找不到名为 name 的参数
  • PO类与分层架构
  • UI前端大数据可视化新实践:如何利用数据动画讲述数据背后的故事?
  • Redis高可用集群一主从复制概述
  • SSH 登录失败,封禁IP脚本
  • 理解Grafana中`X-Scope-OrgID`的作用与配置
  • JavaWeb与HTTP协议
  • 【FPGA】AXI总线协议
  • 李宏毅(deep-leraning)-四---梯度下降batch size
  • 品质童装好而不贵!百胜中台助力久岁伴稳步发展
  • 今日行情明日机会——20250714
  • openEuler系统串口文件手法压力测试及脚本使用说明
  • 破解 VMware 迁移难题:跨平台迁移常见问题及自动化解决方案
  • 我的第一个开源项目:SpringCloud电商前端Vue实战
  • AI驱动编程范式革命:传统开发与智能开发的全维度对比分析
  • 《解锁音频处理新姿势:探索Librosa的无限可能》
  • androidstudio 高低版本兼容
  • 量产技巧之RK3588 Android12默认移除导航栏状态栏​
  • imx6ull-系统移植篇5——U-Boot 顶层 Makefile 简析
  • 蓝象智联入选江苏金融数据开发主体:隐私计算如何赋能公共数据价值释放?
  • Java :编译器的占位符 T#1
  • 【PTA数据结构 | C语言版】字符串匹配算法
  • es的自定义词典和停用词
  • 天海电子闯上市:业绩增速骤降,“踩雷”合众汽车,存坏账风险
  • Go从入门到精通(22) - 一个简单web项目-统一日志输出
  • 5.浏览本地文件获取路径与文件名称 C#例子 WPF例子
  • Elasticsearch 9.x 升级变化
  • 【安卓笔记】线程基本使用:锁、锁案例
  • Windows安装postgreSQL(保姆级教程)