JavaScript 完成线程锁

JavaScript 完成线程锁

ECMAScript 2018 中增加了 SharedArrayBufferAtomics ,应用它们能够完成锁(Lock),即页面主线程和 Web Worker 线程间的锁。

SharedArrayBuffer

SharedArrayBuffer(以下简称为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] = ? :(
}

这时候就需要原子操纵

Atomics

Atomics 能够完成关于 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 的
}

参考

  1. Shared memory and atomics

  2. A Taste of JavaScript’s New Parallel Primitives

  3. https://www.akkadia.org/drepper/futex.pdf

    原文作者:LiuuY
    原文地址: https://segmentfault.com/a/1190000010206888
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞