鸿蒙多线程开发——线程间数据通信对象02

1、前 言

本文的讨论是接续鸿蒙多线程开发------线程间数据通信对象01的讨论。在上一篇文章中,我们讨论了常规的JS对象(普通JSON对象、Object、Map、Array等)、ArrayBuffer。其中讨论了ArrayBuffer的复制传输和转移传输方式。

下面,我们将讨论SharedArrayBuffer。

2、SharedArrayBuffer

SharedArrayBuffer是一种允许多个线程共享相同内存空间的数据通信对象。

这意味着不同的线程可以同时访问和修改相同的数据,而无需复制数据或担心数据同步的问题。SharedArrayBuffer允许我们以更有效的方式进行多线程编程,从而提高性能。

除了SharedArrayBuffer可以直接在多个线程中直接共享外,其他与ArrayBuffer非常类似。

由于SharedArrayBuffer可以在多个线程中直接共享,因此,使用SharedArrayBuffer需要格外小心,以确保线程之间的同步和数据访问是正确的。不正确的访问可能导致内存安全性问题。

为了保证操作的原子性,我们需要使用Atomics类来对数据进行操作。

👉🏻 Atomics

与一般的全局对象不同,Atomics 不是构造函数。我们不能将其与 new 运算符一起使用或将 Atomics 对象作为一个函数来进行调用。

Atomics 的所有属性和方法都是静态的(与 Math 对象一样)。

当SharedArrayBuffer内存被共享时,多个的线程能够读写内存上的同一数据。Atomics原子操作会确保正在读或写的数据的值是符合预期的(即下一个原子操作一定会在上一个原子操作结束后才会开始,其操作不会被中断)。

Atomics提供wait()和notify()机制,采用的是 Linux 上的 futex 模型("快速用户空间互斥体"),可以让进程一直等待直到某个特定的条件为真,主要用于实现阻塞。

Atomics有如下静态方法,用于实现数据的原子操作:

  • Atomics.add(typedArray, index, value)

    将给定的值与数组上指定位置的元素相加,并返回相加前该元素的值。

  • Atomics.and(typedArray, index, value)

    将指定位置上的数组元素与给定的值相与,并返回与操作前该元素的值。

  • Atomics.compareExchange(typedArray, index, expectedValue, replacementValue)

    如果数组中指定的元素与给定的值相等,则将其更新为新的值,并返回该元素原先的值。

  • Atomics.exchange(typedArray, index, value)

    将数组中指定的元素更新为给定的值,并返回该元素更新前的值。

  • Atomics.load(typedArray, index)

    返回数组中指定元素的值。

  • Atomics.notify(typedArray, index, count)

    通知正在等待数组指定索引的代理。返回收到通知的代理数量。

  • Atomics.or(typedArray, index, value)

    将指定位置上的数组元素与给定的值相或,并返回或操作前该元素的值。

  • Atomics.store(typedArray, index, value)

    将值储存到数组的指定位置,并返回该值。

  • Atomics.sub(typedArray, index, value)

    将指定位置上的数组元素与给定的值相减,并返回相减前该元素的值。

  • Atomics.wait(typedArray, index, value, timeout)

    检测数组中某个指定位置上的值是否仍然是给定值,是则保持挂起直到被唤醒或超时。返回值为 "ok"、"not-equal" 或 "time-out"。调用时,如果当前代理不允许阻塞,则会抛出异常(大多数浏览器都不允许在主线程中调用 wait())。

  • Atomics.waitAsync(typedArray, index, value, timeout)

    在共享内存位置上异步等待(即没有阻塞,与 Atomics.wait 不同)并返回一个 Promise。

  • Atomics.xor(typedArray, index, value,)

    将指定位置上的数组元素与给定的值相异或,并返回异或操作前该元素的值。

Atomics的基本使用示例如下:

复制代码
const sab = new SharedArrayBuffer(1024);const ta = new Uint8Array(sab);ta[0]; // 0ta[0] = 5; // 5Atomics.add(ta, 0, 12); // 5Atomics.load(ta, 0); // 17Atomics.and(ta, 0, 1); // 17Atomics.load(ta, 0); // 1Atomics.compareExchange(ta, 0, 5, 12); // 1Atomics.load(ta, 0); // 1Atomics.exchange(ta, 0, 12); // 1Atomics.load(ta, 0); // 12Atomics.or(ta, 0, 1); // 12Atomics.load(ta, 0); // 13Atomics.store(ta, 0, 12); // 12Atomics.sub(ta, 0, 2); // 12Atomics.load(ta, 0); // 10Atomics.xor(ta, 0, 1); // 10Atomics.load(ta, 0); // 11

Atomics等待和通知机制

假设有一个SharedArrayBuffer共享内存。如下:​​​​​​​

复制代码
const sab = new SharedArrayBuffer(1024);const int32 = new Int32Array(sab);

A线程关键代码如下:​​​​​​​

复制代码
Atomics.wait(int32, 0, 0);consle.log(int32[0]); // 123

由于默认情况下,int32[0]值为0,因此A线程将在代码1行上进行阻塞等待。

此时如果启动了B线程,关键代码如下:​​​​​​​

复制代码
console.log(int32[0]); // 0;Atomics.store(int32, 0, 123);Atomics.notify(int32, 0, 1);

B线程启动后,第一行代码可以如期打印出初始化的0,紧接着,向SharedArrayBuffer中第0号位,写入了123,然后再调用了notify,发送出一个解锁通知。

A线程中第1行代码的wait在收到通知后,发现0号位已经不等于0了,则执行下一行代码,打印出了B线程写入的123。

示意图如下:

由于篇幅原因Transferable、Sendable我们在后面介绍。

相关推荐
代码飞一会儿1 小时前
Harmony OS开发之沉浸式模式设计学习
harmonyos·敏捷开发
liulian09163 小时前
Flutter 三方库 flutter_local_auth 的鸿蒙化适配指南
flutter·华为·学习方法·harmonyos
SuperHeroWu73 小时前
【鸿蒙基础入门】概念理解和学习方法论说明
前端·学习·华为·开源·harmonyos·鸿蒙·移动端
亘元有量-流量变现4 小时前
抓住鸿蒙流量红利!2026华为应用商店ASO优化全解
华为·harmonyos·aso优化
特立独行的猫a4 小时前
使用 vcpkg 为OpenHarmony(鸿蒙PC)构建 OpenSSH 命令行工具
harmonyos·openharmony·命令行·openssh·vcpkg·鸿蒙pc
音视频牛哥4 小时前
纯血鸿蒙(HarmonyOS NEXT)下,如何实现低延迟RTSP、RTMP播放器音视频解码?
华为·音视频·harmonyos·鸿蒙rtmp播放器·鸿蒙rtsp播放器·harmonyos rtsp·鸿蒙next播放器
特立独行的猫a6 小时前
OpenSSH 介绍及使用Lycium框架移植到鸿蒙 PC(OpenHarmony)平台的实践总结
harmonyos·openssh·鸿蒙pc·lycium_plusplus·三分库移植
轻口味6 小时前
HarmonyOS 6 轻相机应用开发2:贴纸效果实现
音视频·harmonyos·鸿蒙·播放器
HwJack206 小时前
跨模块资源共享的破局之道:HarmonyOS HSP 资源访问“避坑与升华”指南
华为·harmonyos
liulian09167 小时前
【Flutter for OpenHarmony】原生卡片 Widget 集成实战:从零构建待办清单桌面组件
flutter·华为·学习方法·harmonyos