javascript基础学习系列四百八十八:Atomics 与 SharedArrayBuffer

尽管 HTML 和 Web 应用自诞生以来已经发生了天翻地覆的变化,但 Web 表单几乎从来没有变过。 JavaScript 可以增加现有的表单字段以提供新功能或增强易用性。为此,表单字段也暴露了属性、方法 和事件供 JavaScript 使用。以下是本章介绍的一些概念。
 可以使用标准或非标准的方法全部或部分选择文本框中的文本。
 所有浏览器都采用了 Firefox 操作文本选区的方式,使其成为真正的标准。
 可以通过监听键盘事件并检测要插入的字符来控制文本框接受或不接受某些字符。 所有浏览器都支持剪贴板相关的事件,包括 copy、cut 和 paste。剪贴板事件在不同浏览器中的实现有很大差异。

在文本框只限某些字符时,可以利用剪贴板事件屏幕粘贴事件。
选择框也是经常使用 JavaScript 来控制的一种表单控件。借助 DOM,操作选择框比以前方便了很多。
使用标准的 DOM 技术,可以为选择框添加或移除选项,也可以将选项从一个选择框移动到另一个选择 框,或者重排选项。
富文本编辑通常以使用包含空白 HTML 文档的内嵌窗格来处理。通过将文档的 designMode 属性设 置为"on",可以让整个页面变成编辑区,就像文字处理软件一样。另外,给元素添加 contenteditable 属性也可以将元素转换为可编辑区。默认情况下,可以切换文本的粗体、斜体样式,也可以使用剪贴板功 能。JavaScript 通过 execCommand()方法可以执行一些富文本编辑功能,通过 queryCommandEnabled()、 queryCommandState()和 queryCommandValue()方法则可以获取有关文本选区的信息。由于富文本编 辑区不涉及表单字段,因此要将富文本内容提交到服务器,必须把 HTML 从 iframe 或 contenteditable 元素中复制到一个表单字段。

随着 Web 浏览器能力的增加,其复杂性也在迅速增加。从很多方面看,现代 Web 浏览器已经成为 构建于诸多规范之上、集不同 API 于一身的“瑞士军刀”。浏览器规范的生态在某种程度上是混乱而无 序的。一些规范如 HTML5,定义了一批增强已有标准的 API 和浏览器特性。而另一些规范如 Web Cryptography API 和 Notifications API,只为一个特性定义了一个 API。不同浏览器实现这些新 API 的情 况也不同,有的会实现其中一部分,有的则干脆尚未实现。
最终,是否使用这些比较新的 API 还要看项目是支持更多浏览器,还是要采用更多现代特性。有些 API 可以通过腻子脚本来模拟,但腻子脚本通常会带来性能问题,此外也会增加网站 JavaScript 代码的 体积。

多个上下文访问 SharedArrayBuffer 时,如果同时对缓冲区执行操作,就可能出现资源争用问 题。Atomics API 通过强制同一时刻只能对缓冲区执行一个操作,可以让多个上下文安全地读写一个 SharedArrayBuffer。Atomics API 是 ES2017 中定义的。
仔细研究会发现 Atomics API 非常像一个简化版的指令集架构(ISA),这并非意外。原子操作的本质会排斥操作系统或计算机硬件通常会自动执行的优化(比如指令重新排序)。原子操作也让并发访问 内存变得不可能,如果应用不当就可能导致程序执行变慢。为此,Atomics API 的设计初衷是在最少但 很稳定的原子行为基础之上,构建复杂的多线程 JavaScript 程序。

SharedArrayBuffer

SharedArrayBuffer 与 ArrayBuffer 具有同样的 API。二者的主要区别是 ArrayBuffer 必须 在不同执行上下文间切换,SharedArrayBuffer 则可以被任意多个执行上下文同时使用。
在多个执行上下文间共享内存意味着并发线程操作成为了可能。传统 JavaScript 操作对于并发内存 访问导致的资源争用没有提供保护。下面的例子演示了 4 个专用工作线程访问同一个 SharedArrayBuffer 导致的资源争用问题:

   const workerScript = `
    self.onmessage = ({data}) => {
      const view = new Uint32Array(data);
// 执行1000000次加操作
for (let i = 0; i < 1E6; ++i) {
// 线程不安全加操作会导致资源争用
view[0] += 1;
}
      self.postMessage(null);
    };
`;
const workerScriptBlobUrl = URL.createObjectURL(new Blob([workerScript]));
// 创建容量为 4 的工作线程池 const workers = [];
for (let i = 0; i < 4; ++i) {
      workers.push(new Worker(workerScriptBlobUrl));
    }
// 在最后一个工作线程完成后打印出最终值 let responseCount = 0;
for (const worker of workers) {
      worker.onmessage = () => {
        if (++responseCount == workers.length) {
          console.log(`Final buffer value: ${view[0]}`);
        }
}; }
// 初始化SharedArrayBuffer
const sharedArrayBuffer = new SharedArrayBuffer(4); const view = new Uint32Array(sharedArrayBuffer); view[0] = 1;
// 把 SharedArrayBuffer 发送到每个工作线程 for (const worker of workers) {
      worker.postMessage(sharedArrayBuffer);
    }
//(期待结果为 4000001。实际输出可能类似这样:) // Final buffer value: 2145106

Atomics 与 SharedArrayBuffer

为解决这个问题,Atomics API 应运而生。Atomics API 可以保证 SharedArrayBuffer 上的JavaScript 操作是线程安全的。

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值