SharedArrayBuffer 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区,类似于 ArrayBuffer 对象,它们都可以用来在共享内存(shared memory)上创建视图。与 ArrayBuffer 不同的是,SharedArrayBuffer 不能被分离。
new SharedArrayBuffer(length)
参数length指所创建的数组缓冲区的大小,以字节(byte)为单位。
// 创建一个1024字节的缓冲
let sab = new SharedArrayBuffer(1024);
MDN文档
Atomics 对象提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。
这些原子操作属于 Atomics 模块。与一般的全局对象不同,Atomics 不是构造函数,因此不能使用 new 操作符调用,也不能将其当作函数直接调用。Atomics 的所有属性和方法都是静态的(与 Math 对象一样)。
多个共享内存的线程能够同时读写同一位置上的数据。原子操作会确保正在读或写的数据的值是符合预期的,即下一个原子操作一定会在上一个原子操作结束后才会开始,其操作过程不会中断。
Atomics.add()静态方法会将给定的值加到数组里的某个特定位置上,并返回该位置的旧值。此原子操作保证在写上修改的值之前不会发生其他写操作。
语法: Atomics.add(typedArray, index, value)
// 创建一个16字节的缓冲
let arr = new SharedArrayBuffer(16)
// 创建一个视图,此时图把缓冲内的数据,格式化为一个8位(16字节)的有符号整数数组
let newView = new Int8Array(arr)
Atomics.add(newView, 2, 22) //将下标为2的修改为22, 返回0
// 通过Array.from()将类型数组转化为普通数组
Array.from(newView) // [0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
// 此时arr缓冲区的值也变化le
[[Int8Array]]: Int8Array(16) [0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[[Int16Array]]: Int16Array(8) [0, 22, 0, 0, 0, 0, 0, 0]
[[Int32Array]]: Int32Array(4) [1441792, 0, 0, 0]
[[Uint8Array]]: Uint8Array(16) [0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
静态方法 Atomics.load() 返回一个数组当中给定位置的值。
语法: Atomics.load(typedArray, index)
// 借用上面的代码
Atomics.load(newView, 2) // 22
Atomics.and()静态方法会将给定的值与数组上的值进行按位与操作,并将结果赋值给数组,然后返回数组该位置上的旧值。此原子操作保证在写上修改的值之前不会发生其他写操作。
语法: Atomics.and(typedArray, index, value)
// 按位与操作
5 0101
1 0001
----
1 0001
let arr = new SharedArrayBuffer(8);
let newView = new Uint8Array(arr);
newView[0] = 5;
Atomics.and(ta, 0, 1); // 0 返回此位置的旧值
Atomics.load(ta, 0); // 1
Atomics.or()方法计算数组中给定位置的按位或给定值, 并返回该位置的旧值。此原子操作保证在修改后的值被写回之前不会发生其他写入。
语法:Atomics.or(typedArray, index, value)
// 按位或
5 0101
1 0001
----
5 0101
let sab = new SharedArrayBuffer(8);
let ta = new Uint8Array(sab);
ta[0] = 2;
Atomics.or(ta, 0, 1); // 返回2
Atomics.load(ta, 0); // 3
Atomics.compareExchange()静态方法会在数组的值与期望值相等的时候,将给定的替换值替换掉数组上的值,然后返回旧值。此原子操作保证在写上修改的值之前不会发生其他写操作。
语法: Atomics.compareExchange(typedArray, index, expectedValue, replacementValue)
let arr = new SharedArrayBuffer(8);
let newv = new Uint8Array(arr);
newv[0] = 7;
Atomics.compareExchange(newv, 0, 7, 12); // 返回7, 旧值
Atomics.load(newv, 0); // 12
Atomics.exchange() 静态方法会用 给定的值替换掉数组上的值,然后返回数组的旧值。此原子操作保证在写上修改的值之前不会发生其他写操作。
语法: Atomics.exchange(typedArray, index, value)
let arr = new SharedArrayBuffer(8);
let newv = new Uint8Array(arr);
Atomics.exchange(newv, 0, 12); // 返回0
Atomics.load(newv, 0); // 12
静态的Atomics.store()方法将给定的值存储在数组中的指定位置,并返回该值。.
语法: Atomics.store(typedArray, index, value)
let sab = new SharedArrayBuffer(8);
let ta = new Uint8Array(sab);
Atomics.store(ta, 0, 12); // 12
静态方法Atomics.sub() 减去数组中给定位置的给定值,并在该位置返回旧值。这种原子操作保证了只有修改后的值被写回,才能进行其他的写操作。
语法:Atomics.sub(typedArray, index, value)
let sab = new SharedArrayBuffer(8);
let ta = new Uint8Array(sab);
ta[0] = 48;
Atomics.sub(ta, 0, 12); // 48,返回旧值
Atomics.load(ta, 0); // 36
Atomics.wake()方法唤醒在等待队列中休眠的某些代理
语法:Atomics.wake(typedArray, index, count)
静态Atomics.wait()方法验证 Int32Array 中的给定位置是否仍包含给定值, 如果休眠, 则等待唤醒或超时。它返回一个字符串, 它可以是 “ok”、“不等于” 或 “超时”。
语法: Atomics.wait(typedArray, index, value[, timeout])
// 创建一个共享的视图
let sab = new SharedArrayBuffer(1024);
let int32 = new Int32Array(sab);
// 读取线程正在休眠, 等待位置 0, 预计将为0。只要这是真的, 它就不会继续下去。
//但是, 一旦写入线程存储了一个新值, 它将被写入线程唤醒并返回新值 (123)
Atomics.wait(int32, 0, 0);
console.log(int32[0]); // 123
// 写入线程存储一个新值, 并在它写入后唤醒等待线程:
console.log(int32[0]); // 0;
Atomics.store(int32, 0, 123);
Atomics.wake(int32, 0, 1);