ES8 中的 SharedArrayBuffer,打开无限可能的多线程 Web 应用

在过去,Web 应用的开发主要是单线程的,这意味着 JavaScript 执行环境只有一个线程,也就是说只能同步执行代码。但是,随着 Web 应用变得越来越庞大,单线程的弊端也越来越明显,将会阻断用户的体验,并且在大处理量的任务下很难有效地使用利用 CPU 和硬件资源。为了解决这些问题,多线程技术被引入到 ES8 中,SharedArrayBuffer 就是其中之一。

SharedArrayBuffer 概述

在多线程应用中,各线程共享同一段内存,而 SharedArrayBuffer 是一种新型的 JavaScript 对象,它提供了共享内存的方式,使得多线程能够更高效地工作。它可以被所有线程所共享,并且当一个线程写入了 SharedArrayBuffer 中的数据,其余线程可以立即看到更新的值,从而实现最快的共享内存。

SharedArrayBuffer 对象的全局变量名为 SharedArrayBuffer,其构造函数为 new SharedArrayBuffer(),使用方式和 ArrayBuffer 相似。

下面是一个简单的 SharedArrayBuffer 示例:

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

在这个例子中,我们初始化了一个 4 字节的 SharedArrayBuffer(8 个字节),并将其作为参数输出到 Int32Array 构造函数中,将其转换为一个 32 位数组。现在,操作这个数组的所有线程都可以自由地读取和写入,而且可以保证线程的操作是基于相同数据的。

SharedArrayBuffer 中的原子操作

当多线程应用程序使用共享内存时,必须采取一些特殊的措施,以确保不会导致数据损坏或破坏共享内存的完整性。ES8 提供了原子操作的支持,其中的各个操作原子地执行,以避免在读取和写入共享内存时发生竞态(race conditions)。所有的原子操作都要求在操作开始时给定合适的内存参数和合法的数据长度。

下面是一些常用的原子操作:

  • Atomics.add():原子加操作,将给定值相加并返回结果。
  • Atomics.and():原子与操作,将给定值与对应值按位相与并返回结果。
  • Atomics.exchange():以原子方式替换数组中指定索引的值,并返回原始值。
  • Atomics.wait():等待某个值与数组中指定的索引处的值相等,并返回“ok”或“not-equal”。
  • Atomics.notify():通知正在等待等待某个值与数组中指定的索引处的值相等的线程。

在接下来的代码示例中,我们将演示如何使用原子操作来执行一些基本的操作。

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

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

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

在这个示例中,我们初始值设为全为 0,然后使用 Atomics.add() 和 Atomics.sub() 进行累加和减少。最后,我们使用 Atomics.exchange() 替换数组中的索引 2,从而输出新的数组。

使用 SharedArrayBuffer 构建多线程应用程序

使用 SharedArrayBuffer 和 Atomics 构建多线程应用程序的过程并不像单线程应用程序那样直接。为了实现多线程应用程序,我们需要使用 workers。

Web Worker 是运行在后台的 JavaScript 脚本,其目的是为了开发 Web 应用程序,可以让 JavaScript 在单独的线程上运行。每个 Worker 都有一个高度私有化的作用域,独立于其他页面上的内存。

下面是一个使用 SharedArrayBuffer 和 Atomics 的基本代码示例:

index.html:

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

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

worker.js:

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

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

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

在这个示例中,我们创建了 Worker,并向其发送一个 SharedArrayBuffer。在 worker.js 中,我们将 SharedArrayBuffer 转换为一个 Int32Array,并使用原子操作方式操作其中的数据。最后,我们使用 postMessage 发送处理完的 SharedArrayBuffer。

总结

SharedArrayBuffer & Atomics 是 ES8 中重要的新增特性,它们为我们提供了构建高性能多线程应用程序的机会。共享内存的使用意味着多个线程在读取和写入共享内存时发生竞当问题,为解决这些问题,ES8 引入了原子操作。在使用 SharedArrayBuffer 和 Atomics 之前,我们需要了解一定的底层知识和控制,并小心地使用这些特性以避免可能发生的问题。

我们需要谨慎选择 SharedArrayBuffer 和 Atomics 这些概念。在某些应用场景下,使用多线程可能会导致不必要的复杂性,并导致场景糟糕。但在其他场景下,多线程是迫切需要的,因为它可以显着提升应用程序的性能。通过权衡利弊,并谨慎使用 SharedArrayBuffer 和 Atomics,我们可以进一步拓展 Web 应用程序的潜力。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/647eecb848841e9894e9b53e


猜你喜欢

  • Angular 如何使用管道处理复杂数据

    在前端开发中,数据处理是一个非常重要的环节。而在 Angular 框架中,使用管道可以非常方便地对数据进行筛选、转换和格式化。本文将介绍 Angular 管道的基本用法,并深入探讨如何使用管道处理复杂...

    1 年前
  • Flexbox 实现响应式卡片布局

    在前端开发中,响应式卡片布局十分常见,可以适配不同分辨率和设备,让用户获得更好的体验。而我们可以使用 Flexbox 技术来实现这样的布局。 什么是 Flexbox Flexbox 是一种弹性盒子布局...

    1 年前
  • 如何调试 TypeScript 编写的程序

    TypeScript 是一种静态类型的编程语言,它可以编译成 JavaScript,并且具有类型检查和面向对象的特性。由于 TypeScript 的特殊性,有时候在编写的程序中会出现一些错误和问题,这...

    1 年前
  • 如何将 ESLint 与 Jest 集成

    如何将 ESLint 与 Jest 集成 在前端开发过程中,代码质量和代码测试是非常重要的两个方面。而 ESLint 和 Jest 则是 JavaScript 代码质量和代码测试的两大工具。

    1 年前
  • Sequelize 之使用事务管理数据库操作

    Sequelize 是一个基于 Node.js 的 ORM 框架,适用于各种数据库,如 MySQL、PostgreSQL、SQLite 等。它提供了一种方便的方法来操作数据库,绝大多数情况下可以通过 ...

    1 年前
  • Docker 容器渲染中文字体乱码的解决方法

    前言 在前端领域,我们常常会使用 Docker 容器来构建和部署应用程序。然而,在某些情况下,我们可能会遇到 Docker 容器中文乱码的问题,其中最常见的就是中文字体在容器中无法正确渲染。

    1 年前
  • 在 Express.js 中使用 WebSocket 实现 CRM 解决方案

    CRM(客户关系管理)是现代企业必备的管理工具,通过系统化的方法帮助企业管理客户、销售、营销等各个方面的业务。随着互联网技术的不断发展,越来越多的 CRM 解决方案逐渐向云端移动,在线展示、实时更新的...

    1 年前
  • ES12 中的 WeakSet 解决临时集合存储问题

    前言 在前端开发中,我们经常需要存储一些临时的数据集合,比如临时存储一些已经被选中的 DOM 元素,临时存储一些异步请求的结果等等。而 WeakSet 是 ES6 中引入的新的数据类型,它不同于普通的...

    1 年前
  • ES6 中的 async/await 语法糖及其应用案例

    在编写异步代码时,往往需要嵌套多层回调函数或使用 Promise 对象来处理回调。这不仅使代码难以阅读,而且容易出现一些问题,比如 Promise chaining 和 Promise 的 error...

    1 年前
  • JavaScript 变量解构快速入门

    在 JavaScript 中,我们经常需要从一个对象或者数组中获取某些属性或者元素。在 ES5 中,我们通常使用点操作符或者方括号来获取。然而,在 ES6 中,新增的变量解构语法为我们提供了一种更加简...

    1 年前
  • 利用 SSE 实现实时的反馈信息

    随着互联网的快速发展,我们对即时反馈信息的需求越来越高。在前端开发中,我们经常需要实现实时更新的功能,比如实时聊天、实时推送等等。本文将介绍如何利用 SSE(Server-Sent Events)技术...

    1 年前
  • 如何使用 Enzyme 测试 React 中的图片加载

    在 React 应用中,图片加载通常是不可避免的,但是在测试过程中,图片加载却经常是测试用例难以控制和处理的一部分。Enzyme 是一个流行的 React 测试工具库,它提供了一些有用的工具来测试 R...

    1 年前
  • 如何在 Fastify 框架中实现图形验证码

    随着互联网的发展,验证码已经成为防止机器人攻击和恶意用户的必要工具之一。其中,图形验证码是最常用的一种。本文将介绍如何在 Fastify 框架中实现图形验证码。 什么是 Fastify? Fastif...

    1 年前
  • 无障碍设计:如何让底部导航更友好?

    在现代网页设计中,底部导航条通常被用作网站的主要导航方式。但是,对于一些残障用户来说,底部导航可能会造成一些困扰。比如,存在一些看不到移动设备的用户,底部导航功能区域小而且不易触发,这使得他们在使用网...

    1 年前
  • ES6 语法规范的详细介绍及 Babel 的支持情况

    ES6,也被称为 ECMAScript 2015,是 JavaScript 的标准化版本之一,它为 JavaScript 带来了许多新的语法特性。本文将对 ES6 的一些主要语法特性进行详细介绍,并讨...

    1 年前
  • 利用 PM2 的 load balancer 进行负载均衡

    在实际的前端开发中,应用的访问量往往是不可预测的,为了应对高访问量的情况,我们需要能够更好地并发处理请求。而负载均衡技术恰好能够解决这个问题。在前端领域,我们可以利用 PM2 的 load balan...

    1 年前
  • Vue.js 中使用 Vue-Video-Player 实现视频播放器

    随着移动互联网和视频领域的快速发展,视频播放器已经成为了许多网站和服务的标配,特别是在在线教育和直播等领域。在 Vue.js 中使用 Vue-Video-Player 可以快速实现一个功能强大的视频播...

    1 年前
  • 使用 Koa2 实现基本的文件上传下载功能

    在前端开发中,文件上传和下载是一个非常常见的需求。本文将介绍如何使用 Koa2 实现基本的文件上传和下载功能,包括如何设置路由、处理文件上传、保存文件和提供文件下载等。

    1 年前
  • Cypress自动化测试: 如何在测试中使用Mock数据

    Cypress是一种现代化的前端端对端测试工具,它为我们提供了一种工具,以保证应用程序的质量和正确性。在我们的测试中,我们经常需要使用真实的后端API,这会涉及到很多问题,比如说可用性问题或者费用问题...

    1 年前
  • Material Design中使用RecyclerView实现横向列表的方法总结

    在移动应用程序的设计中,横向滚动列表已经成为常见的设计模式之一。Google开发的Material Design风格也不例外。RecyclerView是最新的Android标准视图,是创建各种复杂列表...

    1 年前

相关推荐

    暂无文章