程序有一个逻辑错误,导致承诺永远不会得到满足(或者如果你来自Java土地,你的Future is never Completed)。结果,该程序挂起。
似乎这种情况可以推广到生产者 - 消费者,生产者会忘记/失去某些东西。
您认为这种情况是什么?是否有术语或短语来描述它?
我不认为死锁是正确的,因为我无法识别循环依赖(necessary conditions for deadlock之一)。 Livelock似乎也不正确,因为线程没有竞争资源 - 他们只是无所事事。
我认为有些人确实将此称为死锁。如果有人能说服我在这种情况下所有的conditions for deadlock都得到满足,那么我会认为这是一个令人满意的答案。
答案 0 :(得分:3)
这称为活动问题。
由于您的代码中存在不同的问题,因此承诺可能会出现 Liveness 的几种不同情况。
图片取自here
如果存在资源争用,并且两个或更多承诺保留了另一个承诺需要进展的资源,并且不会释放它们。当锁定时会发生这种情况。例如,承诺返回函数P1为资源A保持mutex,而P2为资源B保持互斥。为了进展P1需要为A取锁并且为了进展P2需要为A取锁 - 所以两者都无法进展并释放锁定。该计划停止了。
var aPromise = Promise.resolve(); // empty promise
var bPromise = Promise.resolve(); // empty promise
function lockedResourceA(user){
return aPromise = aPromise.then(user);
}
function lockedResourceB(user){
return bPromise = bPromise.then(user);
}
现在,让我们造成僵局:
lockedResourceA(function(a){
return lockedResourceB(b){
// do computation
});
});
lockedResourceB(function(a){
return lockedResourceA(b){
// do computation
});
});
这里计算可能永远不会进展。
无限循环阻止了vat的这种化身再次进步,就像阻止传统线程取得进展一样。与传统线程一样,它不会阻止其他桶(线程)进展。不幸的是,由于每个E对象只在一个大桶中,因此对大桶进行活锁会锁定大桶内的所有对象。 (这类似于对一个持有多个对象的同步锁的线程进行活锁。)
这类似于死锁,而不是承诺说“卡住”每个尝试产生下一个资源。例如,假设在上面的示例中,promise返回函数并不关心它们首先获得哪个资源 - 因此P1和P2每次都尝试生成一个资源,因此它们每个都获得一个交替资源,并且每次都没有完成他们只有一个项目。
这是一个没有底部的递归数据定义 - 例如一个依赖于它自己的承诺或几个递归依赖于彼此的承诺来实现。
例如:
var p = Promise.resolve().then(function(){
return p; // datalock
});
Here is a full wrap up of this problem
从技术上讲,这看起来像是一个典型的死锁,但它是由缺少传出缓冲区引起的。死锁和僵局之间的区别?如果更多的缓冲区空间会导致你还没有锁定,那么它就是僵局而不是死锁。
当您在promise队列中缓冲并且缓冲区空间不足以阻止进度时,会发生这种情况。这与流背压问题密切相关。
当你有一个承诺但没有履行承诺或破坏承诺时,就会发生这种情况。
一个例子,由于Mark Seaborn(谢谢!):如果你有一个抓住时间“等待”(发布为回调)以便解决一个承诺,但是在应该解决它的代码中,你会忘记在所有适用案件中致电
resolve
。当然,实际丢失的信号错误可能比这更复杂。
例如:
var p = new Promise(function(resolve, reject){
// never call resolve
});
p.then(function(){
// never runs
});
这是Mark S. Miller的an excellent summary on the topic。