Java中用位运算|无锁添加状态标记,需用AtomicInteger的getAndOr(Java 9+)或CAS循环(Java 8-)保证原子性,并以2的幂定义互斥标志位,配合&检查、&~清除。

在 Java 中,用位运算 |(按位或)对整型状态变量进行无锁标记添加,本质是利用整数的二进制位表示多个布尔标志,并通过原子操作保证多线程安全。关键不在于“写法”,而在于“如何确保原子性”和“如何设计标志位”。
用 AtomicInteger + getAndOr 保证原子性(Java 9+)
Java 9 引入了 AtomicInteger.getAndOr(int),它原子地执行 current | value 并返回旧值,是最直接、最安全的方式:
- 定义标志常量:每个标志对应一个唯一的 2 的幂,如
public static final int FLAG_A = 1 、FLAG_B = 1 - 声明原子变量:
private final AtomicInteger state = new AtomicInteger(0); - 添加标记:
state.getAndOr(FLAG_A);—— 线程安全,无需 synchronized
兼容 Java 8 及更早版本:用 compareAndSet 循环重试
Java 8 没有 getAndOr,但可用 compareAndSet 实现等效逻辑:
- 读取当前值:
int current = state.get(); - 计算目标值:
int next = current | FLAG_B; - 尝试更新:
if (state.compareAndSet(current, next)) break; - 失败则重试循环 —— 这就是典型的 CAS 自旋,无锁但需注意高竞争下的 CPU 开销
标志位设计必须互斥且可组合
位运算生效的前提是各标志值互不干扰:
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型
- 正确:用
1 定义,如0x01、0x02、0x04、0x08……每一位独立 - 错误:用
1、2、3等非 2 的幂值 ——3占两位,会误改其他标志 - 建议用枚举或接口常量集中管理,避免魔法数字;也可用
EnumSet配合ordinal()映射,但底层仍需转为位掩码
检查与清除也需配套位运算
仅“添加”不够,实际场景常需判断是否已设、或清除某标记:
- 检查是否设置:
(state.get() & FLAG_A) != 0 - 清除标记(无锁):
state.getAndAndUpdate(v -> v & ~FLAG_B)(Java 8+)或用 CAS 循环实现v & ~FLAG - 注意:清除操作不能用
|,必须用& ~flag,否则无效
不复杂但容易忽略:所有操作都依赖整数的位布局和原子变量的线程安全语义,只要标志定义规范、原子操作到位,就能真正实现无锁、高效的状态标记管理。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










