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
。
我的问题是,除了那种情况,发生了什么样的僵局以及避免它们的方法?
答案 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开始,死锁的科夫曼条件为: