ES8新特性——SharedArrayBuffer对象、Atomics对象

SharedArrayBuffer对象

SharedArrayBuffer 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区,类似于 ArrayBuffer 对象,它们都可以用来在共享内存(shared memory)上创建视图。与 ArrayBuffer 不同的是,SharedArrayBuffer 不能被分离。

语法

new SharedArrayBuffer(length)
参数length指所创建的数组缓冲区的大小,以字节(byte)为单位。

  • 需要new运算符构造
// 创建一个1024字节的缓冲
let sab = new SharedArrayBuffer(1024);

MDN文档

Atomics对象

Atomics 对象提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。
这些原子操作属于 Atomics 模块。与一般的全局对象不同,Atomics 不是构造函数,因此不能使用 new 操作符调用,也不能将其当作函数直接调用。Atomics 的所有属性和方法都是静态的(与 Math 对象一样)。
多个共享内存的线程能够同时读写同一位置上的数据。原子操作会确保正在读或写的数据的值是符合预期的,即下一个原子操作一定会在上一个原子操作结束后才会开始,其操作过程不会中断。

  • 注意:Atomics对象的API只能操作SharedArrayBuffer对象的原子,对ArrayBuffer无效

A) Atomics.add()

Atomics.add()静态方法会将给定的值加到数组里的某个特定位置上,并返回该位置的旧值。此原子操作保证在写上修改的值之前不会发生其他写操作。

语法: Atomics.add(typedArray, index, value)

  • 参数:typedArray是一个整型 的类型数组。例如Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,或者Uint32Array。indext, 数组中的位置,该位置数值会被加总并更新。value增加的数字。
  • 返回值: 返回给定位置的旧值
  • 如果typedArray不是符合的格式,就会报错
	// 创建一个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]

B) Atomics.load()

静态方法 Atomics.load() 返回一个数组当中给定位置的值。
语法: Atomics.load(typedArray, index)

	// 借用上面的代码
	Atomics.load(newView, 2)  // 22

C) Atomics.and()

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 

D) Atomics.or()

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

E) Atomics.compareExchange()

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

F) Atomics.exchange()

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

G) Atomics.store()

静态的Atomics.store()方法将给定的值存储在数组中的指定位置,并返回该值。.

语法: Atomics.store(typedArray, index, value)

  • 返回该值
	let sab = new SharedArrayBuffer(8);
	let ta = new Uint8Array(sab);
	
	Atomics.store(ta, 0, 12); // 12

H) Atomics.sub()

静态方法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

I) Atomics.wake()

Atomics.wake()方法唤醒在等待队列中休眠的某些代理

语法:Atomics.wake(typedArray, index, count)

J) Atomics.wake()

静态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);
posted @ 2021-01-29 11:41  sweeeper  阅读(529)  评论(0编辑  收藏  举报