当前位置: 首页 > article >正文

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


http://www.kler.cn/a/404548.html

相关文章:

  • shell--第一次作业
  • python常用的排序算法
  • 【MediaSoup】接收端反馈RTCP调用流程
  • Spring Cloud Alibaba、Spring Cloud 与 Spring Boot各版本的对应关系
  • 缓冲区的奥秘:解析数据交错的魔法
  • VMAuthdService服务启动不了~
  • 用Python爬虫“偷窥”1688商品详情:一场数据的奇妙冒险
  • Scala的Array多维数组
  • 介绍一下strncmp(c基础)
  • 大学课程项目中的记忆深刻 Bug —— 一次意外的数组越界
  • 【Linux】系统调用和库函数汇总整理
  • Ubuntu安装sublime Tex
  • FreeRTOS消息队列实验与出现的问题
  • uni-app 修改复选框checkbox选中后背景和字体颜色
  • redis实现计数器功能
  • 如何取消分词搜索
  • GPT1.0 和 GPT2.0 的联系与区别
  • RabbitMQ实现异步下单与退单
  • 从0开始学习机器学习--Day32--推荐系统作业
  • 统计班级中的说谎者(字节青训)
  • LLM2CLIP:使用大语言模型提升CLIP的文本处理,提高长文本理解和跨语言能力
  • 算法学习笔记(一):滑动窗口和双指针
  • RT_Thread内核源码分析(三)——线程
  • 分布式专题-Redis核心数据结构精讲
  • 《智能指针:明晰资源所有权的 C++利器》
  • 最新Kali安装详细版教程(附安装包,傻瓜式安装教程)