JavaScript死锁

时间:2013-05-13 20:01:26

标签: javascript deadlock infinite-loop

Here我看到了JavaScript死锁和这段代码:

var loop = true,
block = setTimeout(function(){loop = false}, 1);
while(loop);

它肯定是无限循环并导致浏览器冻结。据说是deadlock is created when one operation wait another one to be executed and vice-versa
我的问题是,除了那种情况,发生了什么样的僵局以及避免它们的方法?

2 个答案:

答案 0 :(得分:6)

这不是一个死锁,只是一个无限循环,你不能在JavaScript中遇到死锁,因为你不能有多个线程访问你的数据。

这里发生的是因为你的循环永远不会结束并且js引擎是单线程的(关于你的脚本),调度程序永远不会调用你给setTimeout的回调。事实上,如果没有第二行,你会有完全相同的行为。

答案 1 :(得分:1)

JavaScript 可以死锁,并行执行不是死锁的必要条件。 javascript VM是单线程的,但是它具有并发执行范例,因此可以满足Coffman条件:

这里是一个例子:

function makeFuture() {
  let resolve;
  let reject;
  let promise = new Promise((d, e) => {
    resolve = d;
    reject = e;
  });
  return [promise, resolve, reject];
}

class Lock {
  constructor() {
    this.q = [];
    this.running = false;
  }
  async runQueue() {
    if (this.running) return;
    this.running = true;
    while (this.q.length > 0) {
      const { asyncFunction, resolve, reject } = this.q.shift();
      try {
        let result = await asyncFunction();
        resolve(await asyncFunction());
      } catch (error) {
        reject(error);
      }
    }
    this.running = false;
  }
  runTask(asyncFunction) {
    const [promise, resolve, reject] = makeFuture();
    this.q.push({ asyncFunction, resolve, reject });
    this.runQueue();
    return promise;
  }
}

const dbLock = new Lock();

let taskResultPromise = dbLock.runTask(async () => {
  console.log('about to deadlock');
  let value = await dbLock.runTask(async () => { return 'value'; });
  value //?
  console.log('did not deadlock');
  return value;
});

Wikipedia开始,死锁的科夫曼条件为:

  1. 互斥-Lock类确保对数据库资源的独占并发访问。资源是(数据库锁,“值”值)
  2. 保持并等待-任务1持有db锁并等待任务2中的'value'。任务2持有'value'并等待db lock。
  3. 无抢占-javascript JVM没有机制来强制任一任务抢先释放其锁。
  4. 循环等待-参见(2)。