摘要:实现线程锁中增加了和,利用它们可以实现锁,即页面主线程和线程间的锁。位置的值减去并保存到位置,返回原值。有了上面的和就可以实现一个很简单的线程锁,简单来说,就是利用在多个线程间共享控制位,当控制位为已锁时,则暂停线程,这些操作都依赖。
JavaScript 实现线程锁
ECMAScript 2018 中增加了 SharedArrayBuffer 和 Atomics ,利用它们可以实现锁(Lock),即页面主线程和 Web Worker 线程间的锁。
SharedArrayBufferSharedArrayBuffer(以下简称为SAB) 是一个可以主线程和 Web Worker 线程间共享数据的对象,即同一个 SAB 可以被多个线程读写。
let sab = new SharedArrayBuffer(1024); worker.postMessage(sab);
SAB 避免了多个线程间为了传递数据而进行数据拷贝,但同时缺引入了经典的数据访问「冲突」:
// 线程A let sharedBuffer = new SharedArrayBuffer(1024); let sharedArray = new Int32Array(sab); let worker = new Worker("browser-worker.js"); worker.postMessage(sab); sharedArray[1] = 1; // 线程B onmessage = function (e) { let sharedBuffer = e.data; let sharedArray = new Int32Array(sab); sharedArray[1] = 10; sharedArray[2] = sharedArray[1] + sharedArray[1]; // sharedArray[2] = ? :( }
这时候就需要原子操作。
AtomicsAtomics 可以实现对于 SAB 原子访问,其包含很多操作。
我们下面会用到的:
Atomics.store(typedArray, index, value):向 SAB 的 index 位置赋值 value。
Atomics.wait(typedArray, index, value[, timeout]):验证 Int32Array 的 index 位置是否为给定的 value,是则睡眠(阻塞),否则继续执行。
Atomics.wake(typedArray, index, count):唤醒 Int32Array 的 index 位置上wait 队列(Atomics.wait 产生)。
Atomics.sub(typedArray, index, value):index 位置的值减去 value 并保存到 index 位置,返回原值。
Atomics.compareExchange(typedArray, index, expectedValue, replacementValue):如果 index 位置的值为 expectedValue,则与 replcementValue 交换,返回原值。
Lock有了上面的 SAB 和 Atomics 就可以实现一个很「简单」的线程锁,
简单来说,就是利用 SAB 在多个线程间共享控制位,当控制位为「已锁」时,则暂停线程,这些操作都依赖 Atomics。
注意:这个算法是 Futex,参考了Futexes Are Tricky。
// lock if ((c = Atomics.compareExchange(SAB, index, 0, 1)) !== 0) { // 不为0,说明其他人持锁 do { // 如果依旧得不到锁 if (c === 2 || Atomics.compareExchange(SAB, index, 1, 2) != 0) { Atomics.wait(SAB, index, 2); // 暂停 } // 再次尝试获取锁 } while ((c = Atomics.compareExchange(SAB, index, 0, 2)) !== 0) } // unlock let v0 = Atomics.sub(SAB, index, 1); // 此时拥有锁,状态为1或2 if (v0 != 1) { Atomics.store(SAB, index, 0); // 释放锁 Atomics.wake(SAB, index, 1); // 唤醒一个 wait 的 }参考
Shared memory and atomics
A Taste of JavaScript’s New Parallel Primitives
https://www.akkadia.org/drepper/futex.pdf
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/84044.html
摘要:以多线程的形式,允许单个任务分成不同的部分进行运行。提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。主线程会不断的重复上诉过程。 众所周知,js是单线程的,说到线程,我们首先来仔细辨析一下线程和进程的知识。 一、进程与线程 阮一峰老师的一篇文章写的很好 cpu会给当前进程分配资源,进程是资源分配的最小单位,进程的资源会分配给线程使用,线程是C...
摘要:如果期间有其它线程更新了,则会先拿到新的值重新运算一次多运算的竞争条件这些运算符成功避免了单运算中的竞争条件。 作者:Lin Clark 译者:Cody Chan 原帖链接:Avoiding race conditions in SharedArrayBuffers with Atomics 这是图解 SharedArrayBuffers 系列的第三篇: 内存管理碰撞课程 图...
阅读 3120·2021-11-15 18:14
阅读 1777·2021-09-22 10:51
阅读 3285·2021-09-09 09:34
阅读 3507·2021-09-06 15:02
阅读 1018·2021-09-01 11:40
阅读 3190·2019-08-30 13:58
阅读 2526·2019-08-30 11:04
阅读 1084·2019-08-28 18:31