javascript基础从小白到高手系列六百八十四:原子Futex 操作与加锁

如果没有某种锁机制,多线程程序就无法支持复杂需求。为此,Atomics API 提供了模仿Linux Futex
(快速用户空间互斥量,fast user-space mutex)的方法。这些方法本身虽然非常简单,但可以作为更复杂
锁机制的基本组件。
Atomics.wait()和Atomics.notify()通过示例很容易理解。下面这个简单的例子创建了4 个工
作线程,用于对长度为1 的Int32Array 进行操作。这些工作线程会依次取得锁并执行自己的加操作:
const workerScript = self.onmessage = ({data}) => { const view = new Int32Array(data); console.log('Waiting to obtain lock'); // 遇到初始值则停止,10 000 毫秒超时 Atomics.wait(view, 0, 0, 1E5); console.log('Obtained lock'); // 在索引0 处加1 Atomics.add(view, 0, 1); console.log('Releasing lock'); // 只允许1 个工作线程继续执行 Atomics.notify(view, 0, 1); self.postMessage(null); };;
const workerScriptBlobUrl = URL.createObjectURL(new Blob([workerScript]));
const workers = [];
for (let i = 0; i < 4; ++i) {
workers.push(new Worker(workerScriptBlobUrl));
}
// 在最后一个工作线程完成后打印出最终值
let responseCount = 0;
for (const worker of workers) {
worker.onmessage = () => {
if (++responseCount == workers.length) {
console.log(Final buffer value: ${view[0]});
}
};
}
// 初始化SharedArrayBuffer
const sharedArrayBuffer = new SharedArrayBuffer(8);
const view = new Int32Array(sharedArrayBuffer);
// 把SharedArrayBuffer 发送到每个工作线程
for (const worker of workers) {
worker.postMessage(sharedArrayBuffer);
}
// 1000 毫秒后释放第一个锁
setTimeout(() => Atomics.notify(view, 0, 1), 1000);
// Waiting to obtain lock
// Waiting to obtain lock
// Waiting to obtain lock
// Waiting to obtain lock
// Obtained lock
// Releasing lock
// Obtained lock
// Releasing lock
// Obtained lock
// Releasing lock
// Obtained lock
// Releasing lock
// Final buffer value: 4
因为是使用0 来初始化SharedArrayBuffer,所以每个工作线程都会到达Atomics.wait()并停
止执行。在停止状态下,执行线程存在于一个等待队列中,在经过指定时间或在相应索引上调用
Atomics.notify() 之前, 一直保持暂停状态。1000 毫秒之后, 顶部执行上下文会调用
Atomics.notify()释放其中一个等待的线程。这个线程执行完毕后会再次调用Atomics.notify()
释放另一个线程。这个过程会持续到所有线程都执行完毕并通过postMessage()传出最终的值。
Atomics API 还提供了Atomics.isLockFree()方法。不过我们基本上应该不会用到。这个方法在
高性能算法中可以用来确定是否有必要获取锁。规范中的介绍如下:
Atomics.isLockFree()是一个优化原语。基本上,如果一个原子原语(compareExchange、
load、store、add、sub、and、or、xor 或exchange)在n 字节大小的数据上的原子步骤
在不调用代理在组成数据的n字节之外获得锁的情况下可以执行,则Atomics.isLockFree(n)
会返回true。高性能算法会使用Atomics.isLockFree 确定是否在关键部分使用锁或原子
操作。如果原子原语需要加锁,则算法提供自己的锁会更高效。
Atomics.isLockFree(4)始终返回true,因为在所有已知的相关硬件上都是支持的。
能够如此假设通常可以简化程序。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值