Kotlin Multiplatform for OpenHarmony 实战:kotlinx-atomicfu 原子变量适配

本文是 KMP 三方库鸿蒙化适配,聚焦
kotlinx-atomicfu(Kotlin 官方原子变量库)的 OpenHarmony 适配。我们只讲本仓库真实落地的代码,不做系列横向对比。
目录
摘要
本文是 KMP 三方库鸿蒙化适配系列的一部分,聚焦 Kotlin 官方原子变量库 kotlinx-atomicfu 在 OpenHarmony 上的适配实践。文章采用「纯语义复刻、零 @kit」的三层架构路线:语义层用 ArkTS 实现 AtomicInt / AtomicLong / AtomicBoolean / AtomicRef 的原子读写与 CAS 循环;引擎层以纯复刻工厂 + 并发语义验证的方式提供能力;验收页在真机上验证 1000 次并发自增、CAS 期望值校验与引用交换。文章最后总结了四条踩坑经验,并附上社区与源码链接。
一、为什么选它
kotlinx-atomicfu 是 Kotlin 官方的原子变量库,核心价值是「无锁(lock-free)地操作共享可变状态」:AtomicInt / AtomicLong / AtomicBoolean / AtomicRef + incrementAndGet / compareAndSet 等。它是 kotlinx-coroutines 等并发库的底层基石。
到了 OpenHarmony,ArkTS 是单线程 Actor 模型,原生没有原子变量;但这不代表不能「等价复刻」——原子变量的语义(CAS 循环、期望值校验、引用交换)完全可以忠实保留,让 KMP 源码里 atomic(initial) 的写法在鸿蒙侧有一一对应的实现。这也是本系列「纯语义复刻」路线的又一次实践。
二、适配总思路:三层架构(纯语义复刻,零 @kit)
- 语义层(零
@kit.*):AtomicInt/AtomicLong/AtomicBoolean/AtomicRef只做原子读写 + CAS 循环,不碰任何平台 API。 - 引擎层(无系统桥接):
OhosAtomicfuEngine承担「工厂 + 并发语义验证」,与系列中kotlinx-collections-immutable的纯逻辑引擎层定位一致。 - 验收页:
AtomicfuDemo在真机/模拟器上做 1000 次逻辑并发自增、CAS 期望校验、AtomicRef 引用交换。
三、语义层:CAS 循环是灵魂
Atomicfu.ets 只用 number / boolean / 泛型引用,零平台依赖(注意 ArkTS 严格模式禁止构造参数属性,字段显式赋值):
export class AtomicInt {
private value: number;
constructor(initial: number) { this.value = initial; }
/** 原子自增并返回新值(CAS 循环,lock-free 语义) */
incrementAndGet(): number {
let prev: number;
do {
prev = this.value;
} while (!this.compareAndSet(prev, prev + 1));
return this.value;
}
/** 经典 CAS:期望值命中才更新 */
compareAndSet(expect: number, update: number): boolean {
if (this.value === expect) {
this.value = update;
return true;
}
return false;
}
}
要点:
- lock-free 形态保留:
incrementAndGet用do…while+compareAndSet的循环实现,与 JVM 上 atomicfu 生成的 CAS 循环一一对应。虽然 ArkTS 单线程下不会真的竞争,但 API 形态与无锁算法被忠实保留。 AtomicRef<T>引用语义:CAS 以引用相等判定(与 JavaAtomicReference一致),适合交换不可变对象。AtomicLong用 number 承载:ArkTSnumber是 double,可精确表示至 2^53,足够覆盖 long 语义。
四、引擎层:工厂 + 并发语义验证
OhosAtomicfuEngine.ets 是纯复刻库,没有 HarmonyOS 专属系统能力可桥接,因此只做两件事:
export class OhosAtomicfuEngine {
atomicInt(init: number): AtomicInt { return new AtomicInt(init); }
/** 模拟 N 次逻辑并发自增,CAS 下最终值必须恒等于 N */
benchConcurrentAdds(counter: AtomicInt, iterations: number): { finalValue: number; expected: number; consistent: boolean } {
for (let i = 0; i < iterations; i++) counter.incrementAndGet();
const finalValue = counter.get();
return { finalValue, expected: iterations, consistent: finalValue === iterations };
}
}
这印证了适配策略选择:纯算法/数据结构类库,引擎层可以是「纯复刻工厂 + 能力验证」,不必强行桥接系统 API。
五、验收页:真机上验证
AtomicfuDemo.ets 三个按钮:
- 1000 次并发自增:对
AtomicInt(0)跑 1000 次incrementAndGet,结果区显示最终值 = 1000,期望值 = 1000,CAS 一致 = 是——证明无锁自增语义正确。 - CAS 期望值校验:
AtomicInt(10)先compareAndSet(10,20)成功,再compareAndSet(10,30)失败(值已变 20),结果区显示两次调用的成败与当前值。 - AtomicRef 引用交换:
AtomicRef<{count}>用compareAndSet(旧引用, 新引用)交换对象,证明引用级 CAS 生效。
测试运行效果,结果区会显示稳定的原子语义结果,证明 kotlinx-atomicfu 的能力在鸿蒙真实可用。




六、踩坑小结
- 不要因为 ArkTS 单线程就删掉 CAS 循环:保留
do…while + compareAndSet才能与上游语义对齐,也方便后续迁移到多线程 Worker 场景。 - 严格模式禁止构造参数属性:
constructor(initial: number)内必须显式this.value = initial,不能写成constructor(private value: number)。 AtomicRef用引用相等:CAS 的 expect 必须传「同一引用」,传字面量{count:1}会永远不相等。- long 语义边界:
number精确范围 2^53,超出需用大整数方案(见本系列第 28 篇 kotlinx-bignum)。
总结
本文完整记录了 kotlinx-atomicfu 在 OpenHarmony 上的适配过程,核心结论如下:
- 适配路线:采用「纯语义复刻」策略,不依赖任何
@kit.*平台 API,通过三层架构(语义层、引擎层、验收页)实现与上游语义的一一对应。 - 语义层是灵魂:
AtomicInt等类用do…while + compareAndSet保留 lock-free 形态,AtomicRef以引用相等判定 CAS,AtomicLong用number承载(精确至 2^53)。 - 引擎层定位:纯算法/数据结构类库无需强行桥接系统 API,引擎层只需「纯复刻工厂 + 能力验证」。
- 验收验证:通过 1000 次并发自增、CAS 期望校验、引用交换三个按钮,在真机/模拟器上证明原子语义真实可用。
- 踩坑要点:不要因单线程删掉 CAS 循环、严格模式禁止构造参数属性、
AtomicRef必须传同一引用、long 语义有 2^53 边界。
社区引导
欢迎加入 KMP&CMP 鸿蒙社区:https://atomgit.com/CPF-KMP-CMP
本适配全部源码已开源在 AtomGit:https://atomgit.com/wdracky/kmp-ohos-adapters/tree/main/kotlinx-atomicfu
如果你在适配过程中用到了 AI 辅助工具,推荐码道(AtomCode)专属通道
https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwatomgit1&sourcead=dmzntgwatomgiths
更多推荐



所有评论(0)