Javascript JS&;并发问题?
假设我有简单的代码Javascript JS&;并发问题?,javascript,ajax,javascript-events,concurrency,web-worker,Javascript,Ajax,Javascript Events,Concurrency,Web Worker,假设我有简单的代码 var counter = 0; var sharedResource = [];//some shared resource function incrementAndModify(){ if(counter == 0) { sharedResource.push(Math.random());//very sensitive data counter++; } } function init(){ incrementAndM
var counter = 0;
var sharedResource = [];//some shared resource
function incrementAndModify(){
if(counter == 0) {
sharedResource.push(Math.random());//very sensitive data
counter++;
}
}
function init(){
incrementAndModify();
doAjaxGetWithCallback(function(){incrementAndModify();});
incrementAndModify();
}
所以问题是:incrementAndModify()函数是否会以原子方式运行?我已经读到,JS在单线程上运行,不会有任何并发问题。但问题仍然悬而未决(至少对我而言)
而不是
doAjaxGetWithCallback(function(){incrementAndModify();});
我可以这样写:
doAjaxGetWithCallback(function(){
doSomeCrazyStuffThatDoesNotUseSharedResource();
incrementAndModify();
doSomeOtherCrazyStuffThatDoesNotUseSharedResource();
});
浏览器中的JavaScript是单线程的(s除外),因此您不必担心并发性。本质上,每个代码块都是原子的,不管有多长。如果
incrementAndModify()
执行一些非常耗时的CPU密集型操作,并且AJAX响应到达,则在当前incrementAndModify()
完成并释放唯一线程之前,不会执行回调
这也是不鼓励同步AJAX调用的原因:AJAX请求可能需要一些时间,在此期间无法执行其他代码(执行线程被不必要地占用)。这会导致GUI“冻结”,因为不会处理其他用户事件
另见
doAjaxGetWithCallback(function(){incrementAndModify();});
可以这样写:
doAjaxGetWithCallback(incrementAndModify);
不要担心这只会提醒你一次
// sync example
var happened = false;
setTimeout(dontDoTwice, 0);
setTimeout(dontDoTwice, 0);
setTimeout(dontDoTwice, 0);
function dontDoTwice() {
if (!happened) {
alert("ALERT! ALERT! ALERT!");
happened = true;
}
}
稍微复杂一点的例子:
是的,
incrementAndModify()函数将始终以原子方式运行。这是因为javascript的特性
有关更多详细信息,请参阅。原子意味着什么?我想会一个接一个叫三遍。哪一个问题仍然悬而未决?我有很多想法,但并非所有想法都是正确的。如果你有多个计时器和一个共享资源,你会如何在这段疯狂的代码中进行同步?它们仍然访问相同的I
,这正是你需要担心的调用顺序。JS非常简单,您不能也通常不需要像在线程语言中那样处理这些东西。使此代码同步的方法是将其从计时器中取出。不过,对于您实际试图解决的问题,我有点不确定,因此也许更多的细节可以帮助我提供更有用的答案。我不是在试图解决问题,而是在试图预防问题;)噢,您担心if(count==0)
可能会被调用两次。答案是否定的。回调将在稍后发生。我会用更好的例子更新我的!我不认为您的断言“因此您不必担心并发性”是正确的,即使“每个代码块都是原子的”,我不知道这一点。当您有以某种方式共享状态的回调(或承诺或可观察对象)时,并发问题肯定仍然会发生。即使回调在下一个回调开始之前完全完成,您也必须考虑到不知道这些回调发生的顺序。一次回调很简单,但显然,多次回调的复杂性会变得很大。