4

Let's assume I have simple code:

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

So the question is: Will incrementAndModify() function be run atomically or not? I've read, that JS run on single thread and there can't be any concurrency issues. But the question is still open (at least for me).

Instead of:

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

I could write something like:

doAjaxGetWithCallback(function(){
doSomeCrazyStuffThatDoesNotUseSharedResource();
incrementAndModify();
doSomeOtherCrazyStuffThatDoesNotUseSharedResource();
});
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
hades
  • 1,077
  • 3
  • 11
  • 19

3 Answers3

4

JavaScript in the browser is single-thread (with exception to s), thus you don't have to bother about concurrency. Essentially - every code block is atomic, no matter how long. If incrementAndModify() does some very CPU-intensive time-consuming operations and AJAX response arrives, the callback will not be executed until the current incrementAndModify() finishes and releases the only thread.

This is also the reason why synchronous AJAX calls are discouraged: AJAX request can take some time during which no other code can be executed (execution thread is unnecessarily occupied). This causes the GUI to "freeze", because no other user events are handled.

See also

BTW this:

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

can be written like this:

doAjaxGetWithCallback(incrementAndModify);
Community
  • 1
  • 1
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • I don't think that your assertion "thus you don't have to bother about concurrency" is true, even if "every code block is atomic", which I didn't know. Concurrency problems can certainly still occur when you have callbacks (or Promises or Observables) which in some way share state. Even if a callback finishes completely before the next one starts, you have to make allowance for not knowing the order in which these callbacks happen. Trivial with one callback, but obviously the complexity can become vast with multiple callbacks. – mike rodent Jun 24 '17 at 12:03
0

Yep, the incrementAndModify() function will always run atomically. That's because of the Run-to-Completion feature of javascript.

See Why no concurrency control tool in javascript for more details.

Uzair Farooq
  • 2,402
  • 3
  • 24
  • 37
0

Have no fear this will only ever alert once.

// sync example
var happened = false;

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

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

Slightly more complex example: http://jsfiddle.net/7BZ6H/1/

Jamund Ferguson
  • 16,721
  • 3
  • 42
  • 50
  • and how would you synchronize in this crazy code if you had MANY timers and one shared resource? – hades Mar 21 '12 at 15:28
  • They are still all accessing the same `i`, it's just the order that they might be called that you need to worry about. JS is pretty simple, you can't and usually don't need to do fancy things like you do in threaded languages to handle this stuff. The way to make this code synchronous is to take it out of the timer. I'm a little unsure as to the problem you're actually trying to solve though, so maybe more details would help me provide a more useful answer. – Jamund Ferguson Mar 22 '12 at 16:23
  • I'm not trying to solve a problem, I'm trying yo prevent the problem ;) – hades Mar 27 '12 at 08:30
  • Oooh, you're worried that `if(count==0)` could be called twice. The answer is **no**. The callbacks will happen later. I'll update mine with a better example! – Jamund Ferguson Mar 27 '12 at 17:24