原子类的 getAndUpdate():如何利用函数式接口实现基于当前值的复杂原子业务计算逻辑

阿浩姑娘_2439

阿浩姑娘_2439

2026-05-13

1008人浏览

原创

getAndUpdate()返回旧值,基于CAS循环执行无副作用、幂等的函数式更新,适用于条件更新、状态机跃迁、统计聚合等场景,需避免闭包修改、非幂等操作及长耗时计算。

原子类的 getandupdate():如何利用函数式接口实现基于当前值的复杂原子业务计算逻辑

原子类的 getAndUpdate() 方法允许你基于当前值执行一个确定性的更新操作,并返回更新前的旧值。它接收一个 UnaryOperator(即函数式接口 T → T),让你能用纯函数方式表达“读取当前值 → 计算新值 → 原子写入”的逻辑,避免手动加锁或循环重试。

核心机制:CAS 循环 + 函数式计算

getAndUpdate() 底层依赖 CAS(Compare-And-Swap)自旋,不是简单地“读一次、算一次、写一次”。它会:

  • 读取当前值 current
  • 调用你传入的函数 fn.apply(current) 得到 next
  • 尝试用 CAS 将值从 current 更新为 next
  • 若失败(期间被其他线程修改),则重试:重新读取最新值,再次计算,再 CAS

这意味着你的函数必须是无副作用、幂等、快速完成的——不能依赖外部状态、不能阻塞、不能抛出受检异常(否则需包装为 RuntimeException)。

适用典型场景:非简单加减的原子更新

当 incrementAndGet() 或 addAndGet() 不够用时,getAndUpdate() 就派上用场。例如:

  • 带条件的更新:当前值小于阈值才翻倍,否则归零
    atomicInteger.getAndUpdate(v -> v
  • 状态机跃迁:用整数编码状态(如 0=INIT, 1=RUNNING, 2=STOPPED),实现安全的状态流转
    status.getAndUpdate(s -> s == 0 ? 1 : s); // 仅允许从 INIT → RUNNING
  • 统计聚合:维护最小值,每次用新值和当前最小值比较更新
    minValue.getAndUpdate(v -> Math.min(v, newValue));(注意:这里 newValue 需在闭包中捕获且不变)

与 updateAndGet()、accumulateAndGet() 的关键区别

别混淆这三个方法:

  • getAndUpdate(fn):返回旧值,适合需要“先拿到旧值做判断/记录”再更新的逻辑
  • updateAndGet(fn):返回新值,语义更贴近“更新后立刻要用结果”
  • accumulateAndGet(x, binOp):接收一个二元操作(如 Integer::max),等价于 getAndUpdate(v -> binOp.apply(v, x)),专为“用外部值参与运算”优化,代码更简洁

选哪个取决于你关心的是旧值、新值,还是想省略闭包捕获外部变量的样板代码。

实战提醒:避免常见陷阱

使用时要注意几个易错点:

  • 函数内不要修改外部变量:闭包引用的变量必须是 final 或事实 final;若需累积中间结果,应把状态封装进原子变量本身(如用 AtomicReference)
  • 不保证函数只执行一次:因 CAS 可能失败重试,函数可能被多次调用,务必确保幂等性(比如不要在函数里发 HTTP 请求或写日志)
  • 避免长耗时计算:自旋期间会持续占用 CPU,且增加 CAS 冲突概率;复杂逻辑建议先在外部预计算,再用 compareAndSet() 手动控制
  • 类型匹配要小心:如 AtomicLong 对应 LongUnaryOperator,不是 UnaryOperator(虽然 lambda 写法一样,但编译器推导依赖函数式接口定义)
PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

2023.10.19

3228

3

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

5409

12

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2025.12.29

3889

9

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

2026.01.19

506

15

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

2026.11.06

60

12

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

2026.11.06

20

13

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

2026.11.06

40

10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

2026.11.05

60

12

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

2026.11.05

40

12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.3万人学习