SharedArrayBuffer - JavaScript SharedArrayBuffer 对象
SharedArrayBuffer
SharedArrayBuffer
对象用来表示一个通用的、固定长度的原始二进制数据缓冲区,类似于ArrayBuffer
对象,它们都可以用来在共享内存(shared memory)上创建视图。与ArrayBuffer
不同的是,SharedArrayBuffer
不能被转移。
描述
分配及共享内存
为了将一个SharedArrayBuffer
对象从一个用户代理共享到另一个用户代理(另一个页面的主进程或者当前页面的一个worker
)从而实现共享内存,我们需要运用postMessage
和结构化克隆算法。
结构化克隆算法接收SharedArrayBuffers
对象,或被映射到一个新的SharedArrayBuffers
对象上的TypedArrays
对象。在这两种情况下,这个新的SharedArrayBuffer
对象会被传递到目标用户代理的接收函数上,从而在目标用户代理产生一个新的私有SharedArrayBuffer
对象(正如ArrayBuffer
一样)。但是,这两个SharedArrayBuffer
对象指向的共享数据块其实是同一个,所以某一代理对数据块的修改在另一个代理中可见。
var sab = new SharedArrayBuffer(1024); worker.postMessage(sab);
通过原子操作更新及同步共享内存
共享内存能被同时创建和更新于worker
线程或主线程。依赖于系统(CPU、操作系统、浏览器),变化传递给所有上下文环境需要一段时间。因此需要通过原子操作来进行同步。
接受 SharedArrayBuffer 对象的 API
WebGLRenderingContext.bufferData()
WebGLRenderingContext.bufferSubData()
(en-US)WebGL2RenderingContext.getBufferSubData()
(en-US)
安全需求
为应对幽灵漏洞,所有主流浏览器均默认于 2018 年 1 月 5 日禁用 SharedArrayBuffer。在 2020 年,一种新的、安全的方法已经标准化,以重新启用SharedArrayBuffer
。通过一些安全措施,postMessage()
将不再抛出有关SharedArrayBuffer
对象的异常,跨线程共享内存也变得可用:
作为基准需求,你的文档需处于安全上下文中。
对于顶级文档,需要设置两个 HTTP 消息头以跨域隔离你的站点:
Cross-Origin-Opener-Policy
(en-US)设置为same-origin
(保护源站免受攻击)Cross-Origin-Embedder-Policy
设置为require-corp
(保护源站免受侵害)
Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp
为检查跨域隔离是否生效,你可以检查crossOriginIsolated
属性在窗口和worker
上下文中是否可用:
if (crossOriginIsolated) { // Post SharedArrayBuffer } else { // Do something else }
参阅 Planned changes to shared memory (en-US),以了解共享内存在浏览器中的变更计划(例如,Firefox 79)。
始终使用 new 运算符来构造 SharedArrayBuffer
SharedArrayBuffer
必须使用new
运算符来构造。作为函数来调用SharedArrayBuffer()
构造函数(如果不用new
运算符),将会抛出TypeError
异常。
var sab = SharedArrayBuffer(1024); // TypeError: calling a builtin SharedArrayBuffer constructor // without new is forbidden
var sab = new SharedArrayBuffer(1024);
构造函数
SharedArrayBuffer()
创建一个SharedArrayBuffer
对象。
实例属性
SharedArrayBuffer.prototype.byteLength
数组的大小(以字节为单位)。这是在构造数组时建立的,不能更改(只读)。
实例方法
SharedArrayBuffer.prototype.slice(begin, end)
返回一个新的SharedArrayBuffer
,其为源数组从begin
字节到end
字节(不含end
字节)的拷贝。若begin
或end
为负数,则表示从数组末尾开始的索引。
示例
创建一个新的 SharedArrayBuffer
var sab = new SharedArrayBuffer(1024);
截取 SharedArrayBuffer
sab.slice(); // SharedArrayBuffer { byteLength: 1024 } sab.slice(2); // SharedArrayBuffer { byteLength: 1022 } sab.slice(-2); // SharedArrayBuffer { byteLength: 2 } sab.slice(0, 1); // SharedArrayBuffer { byteLength: 1 }
在 WebGL buffer 中使用
const canvas = document.querySelector('canvas'); const gl = canvas.getContext('webgl'); const buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, sab, gl.STATIC_DRAW);
鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com
图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!