鸿蒙多线程开发——线程间数据通信对象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我们在后面介绍。

相关推荐
Random_index3 小时前
#Uniapp篇:支持纯血鸿蒙&发布&适配&UIUI
uni-app·harmonyos
芋芋qwq5 小时前
Unity UI射线检测 道具拖拽
ui·unity·游戏引擎
SuperHeroWu79 小时前
【HarmonyOS】鸿蒙应用接入微博分享
华为·harmonyos·鸿蒙·微博·微博分享·微博sdk集成·sdk集成
大霞上仙9 小时前
element ui table 每行不同状态
vue.js·ui·elementui
zhangjr057511 小时前
【HarmonyOS Next】鸿蒙实用装饰器一览(一)
前端·harmonyos·arkts
栈老师不回家17 小时前
Element UI 组件库详解【Vue】
前端·vue.js·ui
诗歌难吟46418 小时前
初识ArkUI
harmonyos
SameX18 小时前
HarmonyOS Next 设备安全特性深度剖析学习
harmonyos
郭梧悠19 小时前
HarmonyOS(57) UI性能优化
ui·性能优化·harmonyos