JS&并发问题?

时间:2012-03-21 15:02:17

标签: javascript ajax javascript-events concurrency

我们假设我有简单的代码;

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();
});

3 个答案:

答案 0 :(得分:3)

浏览器中的JavaScript是单线程的( s除外),因此您不必担心并发问题。本质上 - 每个代码块都是原子的,无论多长时间。如果incrementAndModify()执行一些非常耗费CPU的耗时操作并且AJAX响应到达,则在当前incrementAndModify()完成并释放唯一线程之前,不会执行回调。

这也是不鼓励同步AJAX调用的原因:AJAX请求可能需要一些时间,在此期间不能执行其他代码(执行线程被不必要地占用)。这会导致GUI“冻结”,因为没有其他用户事件被处理。

另见

BTW:

doAjaxGetWithCallback(function(){incrementAndModify();});

可以这样写:

doAjaxGetWithCallback(incrementAndModify);

答案 1 :(得分:0)

不要害怕这只会警惕一次。

// sync example
var happened = false;

setTimeout(dontDoTwice, 0);
setTimeout(dontDoTwice, 0);
setTimeout(dontDoTwice, 0);

function dontDoTwice() {
  if (!happened) {
    alert("ALERT! ALERT! ALERT!");
    happened = true;
  }
}

稍微复杂的例子: http://jsfiddle.net/7BZ6H/1/

答案 2 :(得分:0)

是的,incrementAndModify()函数将始终以原子方式运行。这是因为javascript的Run-to-Completion功能。

有关详细信息,请参阅Why no concurrency control tool in javascript