javascript基础从小白到高手系列一百八十二:原子操作基础

本文介绍了JavaScript中的Atomics对象及其提供的原子操作方法,如算术和位操作,如何在SharedArrayBuffer中执行线程安全操作,以及如何避免线程不安全问题,通过使用工作线程和原子操作确保数据一致性。
摘要由CSDN通过智能技术生成

任何全局上下文中都有Atomics 对象,这个对象上暴露了用于执行线程安全操作的一套静态方法,
其中多数方法以一个TypedArray 实例(一个SharedArrayBuffer 的引用)作为第一个参数,以相
关操作数作为后续参数。

  1. 算术及位操作方法
    Atomics API 提供了一套简单的方法用以执行就地修改操作。在ECMA 规范中,这些方法被定义为
    AtomicReadModifyWrite 操作。在底层,这些方法都会从SharedArrayBuffer 中某个位置读取值,
    然后执行算术或位操作,最后再把计算结果写回相同的位置。这些操作的原子本质意味着上述读取、修
    改、写回操作会按照顺序执行,不会被其他线程中断。
    以下代码演示了所有算术方法:
    // 创建大小为1 的缓冲区
    let sharedArrayBuffer = new SharedArrayBuffer(1);
    // 基于缓冲创建Uint8Array
    let typedArray = new Uint8Array(sharedArrayBuffer);
    // 所有ArrayBuffer 全部初始化为0
    console.log(typedArray); // Uint8Array[0]
    const index = 0;
    const increment = 5;
    // 对索引0 处的值执行原子加5
    Atomics.add(typedArray, index, increment);
    console.log(typedArray); // Uint8Array[5]
    // 对索引0 处的值执行原子减5
    Atomics.sub(typedArray, index, increment);
    console.log(typedArray); // Uint8Array[0]
    以下代码演示了所有位方法:
    // 创建大小为1 的缓冲区
    let sharedArrayBuffer = new SharedArrayBuffer(1);
    // 基于缓冲创建Uint8Array
    let typedArray = new Uint8Array(sharedArrayBuffer);
    // 所有ArrayBuffer 全部初始化为0
    console.log(typedArray); // Uint8Array[0]
    const index = 0;
    // 对索引0 处的值执行原子或0b1111
    Atomics.or(typedArray, index, 0b1111);
    console.log(typedArray); // Uint8Array[15]
    // 对索引0 处的值执行原子与0b1111
    Atomics.and(typedArray, index, 0b1100);
    console.log(typedArray); // Uint8Array[12]
    // 对索引0 处的值执行原子异或0b1111
    Atomics.xor(typedArray, index, 0b1111);
    console.log(typedArray); // Uint8Array[3]
    前面线程不安全的例子可以改写为下面这样:
    const workerScript = self.onmessage = ({data}) => { const view = new Uint32Array(data); // 执行1 000 000 次加操作 for (let i = 0; i < 1E6; ++i) { // 线程安全的加操作 Atomics.add(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: 4000001
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值