futuretask 的线程安全依赖状态机+volatile+ cas 协同机制:volatile state 保证可见性与 happens-before,cas 确保状态跃迁唯一性,7 种不可逆状态构成严格跃迁图谱,get() 等待通过无锁 waiters 栈实现唤醒。

FutureTask 的线程执行安全,不靠锁,而是靠一套精巧的状态机 + volatile + CAS 协同机制实现。它把“任务是否在跑、结果有没有、能不能取消”这些关键判断,全部收敛到一个原子状态字段 state 上,并通过严格的状态跃迁规则杜绝竞态。
volatile state 是状态可见性的基础
state 被声明为 volatile int,这意味着:
- 所有线程读写 state 都直通主内存,不会因 CPU 缓存导致看到过期值
- 对 state 的写操作,对其后读取 outcome、runner 等字段的操作形成 happens-before 关系,保证结果数据不会被重排序读取
- 配合状态机语义,一个线程看到 state == NORMAL,就能确信 outcome 已写入且可见
CAS 控制状态跃迁的唯一性
FutureTask 不允许任意修改 state,所有关键动作都必须通过 CAS “先检查再设置”:
- run() 启动前:仅当 state == NEW 时,才尝试用 CAS 设置 runner 并进入执行逻辑;失败说明已被其他线程抢先启动或取消
- set(v) 或 setException(ex):只允许从 COMPLETING 状态 CAS 到 NORMAL 或 EXCEPTIONAL;中间态 COMPLETING 本身也由 CAS 进入,防止重复写入
- cancel(true/false):分别尝试从 NEW → INTERRUPTING → INTERRUPTED 或 NEW → CANCELLED;CAS 失败即说明任务已开始完成或被取消,无需重试
7 种状态构成不可逆的跃迁图谱
FutureTask 定义了 7 个明确状态(NEW、COMPLETING、NORMAL、EXCEPTIONAL、CANCELLED、INTERRUPTING、INTERRUPTED),它们之间只有合法路径:
- NEW → COMPLETING → NORMAL(正常完成)
- NEW → COMPLETING → EXCEPTIONAL(异常完成)
- NEW → CANCELLED(未启动即取消)
- NEW → INTERRUPTING → INTERRUPTED(运行中被中断)
没有回退、没有交叉,每个终态(NORMAL/EXCEPTIONAL/CANCELLED/INTERRUPTED)都是最终且唯一的。一旦进入终态,后续任何 get()、cancel()、run() 调用都按终态语义处理,不会触发二次计算或状态覆盖。
等待与唤醒也遵循无锁状态驱动
多个线程调用 get() 时,若任务未完成,它们不会自旋或加锁排队,而是:
- 构造 WaitNode,以 CAS 方式压入 volatile waiters 栈顶
- 任务完成时(state 进入终态),FutureTask 遍历 waiters 栈,逐个 unpark 线程
- 唤醒顺序为 LIFO,但语义上无关紧要——因为 outcome 已写入、state 已终态,每个 get() 都能立即返回或抛异常
整个过程不依赖 synchronized 或 ReentrantLock,所有同步都由 volatile 读写和 CAS 操作隐式保障。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











