ES9 中的 SharedArrayBuffer 和 Atomics,实现多线程的新利器

在这个信息化时代,越来越多的应用程序需要同时处理众多数据,甚至跨多个应用程序之间协作完成任务。在这种情况下,多线程技术就显得尤为重要。在传统的前端开发中,由于 JavaScript 单线程的特性,多线程编程都是通过 Web Workers 来实现,但 Web Workers 的缺点也是比较明显的:不能在多个线程之间直接共享内存空间,这样可能导致内存浪费和多线程同步问题。ES9 中的 SharedArrayBuffer 和 Atomics 提供了一种新的方法来解决这个问题,为前端多线程带来了新的工具。

SharedArrayBuffer

SharedArrayBuffer 是一种新类型的 ArrayBuffer,它可以在所有的共享的 Worker、ServiceWorker 或 iframe 中使用,并且可以在这些线程之间直接共享内存空间。

对于共享内存空间的使用,关键的问题是如何协调多个线程对于同一块内存的访问。这将涉及到线程同步和竞争条件等问题,后文将介绍 Atomics 来解决这些问题。

SharedArrayBuffer 的使用方法与 ArrayBuffer 非常相似,只需要将类型从 ArrayBuffer 替换为 SharedArrayBuffer,例如:

----- --- - --- ------------------------
----- -------- - --- ----------------

上述代码中,首先创建了一个长度为 1024 字节的 SharedArrayBuffer,然后通过 Int32Array 视图创建了一个 32 位整数类型的数组。这样,在所有共享同一个 SharedArrayBuffer 的线程中,都可以直接访问到 intArray 数组中的数据,从而实现了数据的共享。

需要注意的是,由于 SharedArrayBuffer 直接共享内存的特性,为了保证安全性,对 SharedArrayBuffer 的访问是基于线程间所使用的同一种源或文档来进行的,这样可以保证共享内存的各种操作都是可控的。

Atomics

在多线程编程中,一个常见的场景就是需要同步多个线程对于共享数据的读写。如果没有同步和协调,就很容易出现类似竞争条件、死锁这样的问题,这会使程序出现非常严重的错误。

Atomics 对象提供了一套原子性的操作,这些操作可以对多个线程并发访问的 SharedArrayBuffer 中的数据进行操作,并且保证这些操作的原子性,从而避免了线程同步和竞争条件等问题。

在使用 Atomics API 时,需要注意以下几点:

  • Atomics 操作的目标必须是 SharedArrayBuffer 中的一个元素
  • Atomics 操作的结果是原子性的,不会被其他线程中断或干扰
  • Atomics 操作与 JavaScript 的 Event Loop 基本无关,要考虑它们之间的关系需要特别注意

下面是 Atomics 引入的一些操作:

add

将 SharedArrayBuffer 中的指定位置中的值与给定的值相加,并返回相加后的新值。

------------------------------ ------ -------

示例代码:

--- ----------------- - --- ------------------------
--- ---------- - --- ------------------------------

--- ----- - --- -- -- -- ---
--- ---- - - -- - - ------------- ---- -
  ----------------------- -- ----------
-

------------------------ -- ---------- - -- -- -- --- --- -- -- --- -

and

将 SharedArrayBuffer 中的指定位置中的值与给定的值进行按位与(&)运算,并返回运算后的新值。

------------------------------ ------ -------

示例代码:

--- ----------------- - --- ------------------------
--- ---------- - --- ------------------------------

--- ---- - - -- - - ------------------ ---- -
  ------------------------- -- ----
-

----------------------- -- ---
------------------------ -- ---------- - --- -- --- --- --- --- --- --- -

load

返回 SharedArrayBuffer 中指定位置的值。

------------------------------- -------

示例代码:

--- ----------------- - --- ------------------------
--- ---------- - --- ------------------------------

------------------------- -- -----
------------------------------------ ---- -- ---

or

将 SharedArrayBuffer 中的指定位置中的值与给定的值进行按位或(|)运算,并返回运算后的新值。

----------------------------- ------ -------

示例代码:

--- ----------------- - --- ------------------------
--- ---------- - --- ------------------------------

--- ---- - - -- - - ------------------ ---- -
  ------------------------- -- ----
-

---------------------- -- ---
------------------------ -- ---------- - --- --- --- --- --- --- --- --- -

store

将特定值存储到 SharedArrayBuffer 中指定位置,无需查询原位置的值。

-------------------------------- ------ -------

示例代码:

--- ----------------- - --- ------------------------
--- ---------- - --- ------------------------------

------------------------- -- -----
------------------------ -- ---------- - ---- -- -- -- -- -- --- -

sub

将 SharedArrayBuffer 中的指定位置中的值与给定的值相减,并返回相减后的新值。

------------------------------ ------ -------

示例代码:

--- ----------------- - --- ------------------------
--- ---------- - --- ------------------------------

--- ---- - - -- - - ------------------ ---- -
  ------------------------- -- ----
-

----------------------- -- ---
------------------------ -- ---------- - --- -- --- --- --- --- --- --- -

xor

将 SharedArrayBuffer 中的指定位置中的值与给定的值进行按位异或(^)运算,并返回运算后的新值。

------------------------------ ------ -------

示例代码:

--- ----------------- - --- ------------------------
--- ---------- - --- ------------------------------

--- ---- - - -- - - ------------------ ---- -
  ------------------------- -- ----
-

----------------------- -- ---
------------------------ -- ---------- - --- -- --- --- --- --- --- --- -

总结

在 ES9 中,SharedArrayBuffer 和 Atomics 是 JavaScript 多线程实现的新工具。SharedArrayBuffer 提供了一种直接共享内存的方式,而 Atomics 提供了原子性操作,可确保多线程程序的线程同步和竞争条件等问题被解决。虽然 ES9 中的多线程功能仍然比较基础,但这对于大多数前端开发者来说是一个重大的进步,可以让他们更好地处理高并发数据场景。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6647d72fd3423812e4661beb