javascript - 实现递归锁

标签 javascript typescript async-await

我创建了一个 Synchronizable mixin,它提供了 synchronized 功能:

const lock = Symbol('Synchronizable lock');
const queue = Symbol('Synchronizable queue');

export class Synchronizable {
  private [lock] = false;
  private [queue]: Array<() => void> = [];

  public async synchronized<T>(fn: () => Promise<T>): Promise<T> {
    while (true) {
      if (this[lock]) await new Promise(resolve => this[queue].push(resolve));
      else {
        this[lock] = true;
        try {
          return await fn();
        } finally {
          this[lock] = false;
          const tmp = this[queue];
          this[queue] = [];
          tmp.forEach(e => e());
        }
      }
    }
  }
}

但是加锁不是递归的,加锁时加锁对象会造成死锁:

const c = new Synchronizable();
await c.synchronized(() => c.synchronized(async () => void 0));

如何实现递归锁?

完整代码上传至github带测试用例

第一个想法

就像任何其他语言一样,在锁定时保存当前线程 ID,然后将保存的线程 ID 与当前线程 ID 进行比较,如果匹配则继续。

但 javascript 不提供线程 ID,延迟闭包不会生成新的 ID。

再想一想

跟踪调用堆栈,在堆栈中找到任何其他锁调用,检查它是否是同一个锁。

问题是堆栈跟踪可能不会跟随回调,例如 setTimeout,因此它无法在回调之前检测到锁。

最佳答案

我发现使用第一种方法可以通过 Zone.js 实现,其中 Zone.js 提供了一种定义线程局部变量的方法。

关于javascript - 实现递归锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53849947/

相关文章:

javascript - 如何捕获异步函数重新抛出的错误?

javascript - AngularJS 找不到模板

javascript - React - 未捕获类型错误 : this. getDOMNode 不是函数

javascript - 如何使用字符串定义的函数输入常量?

Javascript 在本地存储中保存和检索数组数据

javascript - jQuery 加载的异步和就绪函数不起作用

javascript - 仅跟踪嵌套 div 标记中悬停子元素的鼠标移动

javascript - Firebase Web 代码实验室 : missing app configuration value "appId"

javascript - 如何在补丁请求后更新行为主体?

c# - .NET 任务的性能指标/诊断