java状态机并发安全的核心是用不可变状态+atomicreference实现原子跃迁,转移逻辑需幂等无副作用,高并发下应线程封闭实例并避免全局锁,虚拟线程仍须隔离共享状态。

用不可变状态 + 原子引用替代可变字段
状态本身应设计为不可变(如枚举),当前状态的持有者必须是线程安全的容器:✅ 推荐方式:用 AtomicReference
- State 是枚举(如
INIT,WAIT_PAY,PAID),天然不可变 - 所有状态变更都通过
compareAndSet(oldState, newState)实现原子跃迁 - 失败时可重试或拒绝,不破坏一致性
❌ 避免直接用 volatile State currentState + 普通赋值——无法保证“读-判-写”三步整体原子性
转移规则与动作需幂等且无共享副作用
状态转换过程中的业务逻辑(如扣库存、发消息)必须满足:✅ 关键要求:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 条件判断(如金额校验)应在
compareAndSet前完成,且不依赖中间状态快照 - 转移动作(
Runnable或 lambda)不能修改其他共享变量,或自身已做线程安全封装 - 若动作含 I/O 或远程调用,建议异步化并记录操作日志,便于补偿
高并发场景下优先使用无锁结构
当状态机被大量线程高频触发(如订单创建峰值),应避开 synchronized 或 ReentrantLock:✅ 更优组合:
- ConcurrentHashMap 存储「状态+事件→目标状态」规则表,支持并发读、低频写
- AtomicInteger 或 LongAdder 统计各状态流转次数,无需锁
- 对每个业务实体(如一个订单 ID)使用独立状态机实例,天然隔离——这是最轻量的线程封闭
⚠️ 注意:不要为整个状态机类加全局锁,会成为性能瓶颈
虚拟线程环境下仍需谨慎对待共享状态
即使使用Thread.ofVirtual() 启动百万级线程,只要它们共用同一个状态机实例,竞态风险不变:
✅ 正确做法:
- 每个虚拟线程操作自己专属的订单/任务对象,其内部状态由
AtomicReference管理 - 避免在 callable 中闭包捕获外部可变对象(如
int[] counter) - 若需聚合结果,用 CopyOnWriteArrayList 或 ConcurrentLinkedQueue 收集,而非普通 ArrayList
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










