Tl;dr

It just can't happen. There are no multi-threaded problems in a single threaded environment. My apologies to all of the setTimeouters out there.

<Rant>  

I thought it is rather clear

But it isn't.
JavaScript is widely used everywhere. from a language that was used to play with the DOM for fun and leisure it is now a major language used to build servers, program mobile applications or even run hardware.
But still, a lot developers don't take JavaScript seriously. I read once a nice article written by Douglas Crockford titled "The World's Most Misunderstood Programming Language". He states a few reasons why JavaScript is misunderstood. This article was written in 2001. Not a lot have changed since then. The language has a lot more advocates and is the top 7 programming language used in 2014, but even this page describes the language as :

A scripting language used primarily to add functionality to Web browsers on the fly, allowing the creation of complex Web pages.

Those times are over. Get over it.

Back to race conditions

What are race conditions (in software)?

The short description would be - when two threads are accessing the same resource at the same time and modify it the result is unexpected. No one can assure that the variable that was changed or the service that was accessed has been modified or accesed by the first or the second thread. Whoever wins, wins.
There are many solutions for race conditions (Semaphores/Mutex, atomic operations, and others). But guess what? JavaScript needs none of those. Every operation is atomic!

An example of loading a URL

Let'S see how different paradigms handle a simple network request of a simple resource.

The Java way

In Java it would look like this:

// Open an input stream
InputStream is = new URL(url).openStream();  
//Connection is already made!
try {  
  // read the buffer
  BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
  // a magical conversion function
  String jsonText = convertToString(rd);
  JSONObject json = new JSONObject(jsonText);
  // return the JSON object. Synchronous
  return json;
} finally {
  is.close();
}

This works wonderfully. Until the URL is not reachable. Then the fun starts! This code will halt (including UI updates, if ran on the UI thread), until a certain timeout was defined. Even Android doesn't allow network connections on the UI thread, exactly for that reason. The fact that Android's NetworkOnMainThreadException was needed (was introduced only in Version 3) only shows that this was a rather major problem of quite a lot of applications and developers.
Let's say the JSON information that was downloaded (A String, eventually) needs to be appended to a string variable. If two requests were made in two different threads (as we would expect) and they return at the same time, they will alter the variable at the same time as well. The results in this case are unexpected. Both will parallel append information to it. This is a classic race condition - who will win? thread 1 or 2? Probably both.
There are, of course, solutions for that. In this specific case, file lock would come in handy. Promises were introduced in many languages, certain libraries like QT have their way of handling this. But I find the JavaScript way to be the best.

The JavaScript way

JavaScript executes tasks that are defined asynchronous only AFTER the scope that fired them ended. And in JavaScript, anything that is a blocking operation is executed asynchronously. Let's understand what this means. If you are a Java developer, you will always wonder why this works:

var xmlhttp = new XMLHttpRequest();  
var url = "myTutorials.txt";

//open the connection
xmlhttp.open("GET", url, true);  
//send the request
xmlhttp.send();

//Callback set after connection opened and request sent. And still works! 
xmlhttp.onreadystatechange = function() {  
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        var myArr = JSON.parse(xmlhttp.responseText);
        myFunction(myArr);
    }
}

This is possible, because the HTTP request is only executed after the current scope has ended its tasks. This enables the programmer to set the callbacks at any position he wishes. As JavaScript is single-threaded, the request can only be sent when this one single thread is free to run new tasks. The HTTP request is added to the list of tasks to be executed, that is managed by the engine.

For example, this code will never sent the request:

var xmlhttp = new XMLHttpRequest();  
var url = "myTutorials.txt";

//open the connection
xmlhttp.open("GET", url, true);  
//send the request
xmlhttp.send();

//prevent the scope from ending
while(true) {}  

The HTTP request is added as the next task to execute, but the scope never ends its own execution.
The same goes to loading an object from IndexedDB, a click event or executing a worker. None of those actually executes at the time they were requested.

Saying this is a proof for race conditions:

var xmlhttp = new XMLHttpRequest();  
var url = "myTutorials.txt";

//open the connection
xmlhttp.open("GET", url, true);  
//send the request
xmlhttp.send();

window.setTimeout(function() {  
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            var myArr = JSON.parse(xmlhttp.responseText);
            myFunction(myArr);
        }
    }
}, 5000);

is wrong. This may or may not work, depends on how long it takes the request to run. This is, however, not a race condition. No two threads are trying to execute the onreadystatechange or the myFunction(myArr) function at the same time. It will execute when the request has arrived on the same (single) thread the request came from.
There is of course no reason for the developer to ever do such a thing. Why would someone want to define the callback N ms after a request was made?
I might be seeing race conditions a bit different than other developers. I see that as a problem that the system itself presents. Not a mistake made by the developer. In JavaScript there is no possible way of accessing the same resource at the same time. It will never be at the same time, not even with workers (as I explained in my post about inline workers). Even if two requests were made at the same time (which is technically impossible, but let's call it "at the same time") and they return at the same time (which is possible), their callbacks will never execute at the same time. One callback will be executed after the other, leaving the string variable (from the Java example) we append the information to in order.

You may argue with me. When reading this definition:

A race condition is an undesirable situation that occurs when a device or system attempts to perform two or more operations at the same time, but because of the nature of the device or system, the operations must be done in the proper sequence to be done correctly.

taken from http://searchstorage.techtarget.com/definition/race-condition, you might argue that JavaScript does have race conditions (and you could give the exact same example I gave before with the setTimeout).
You may argue that two parallel dependent HTTP requests also presents a race condition. I would say, again, that there is no reason to do that at all. If a request is dependent on a different request, the fact the you executed them one after the other and not the 2nd after the 1st has returned is your design error, not the system's fault.

So -

  1. Every action in JavaScript is atomic.
  2. By design, JavaScript allows no deadlock (prove me wrong :-). And no, that's NOT a deadlock. It is an infinite loop. )
  3. I wouldn't call the bad practice of setting callbacks at a future state of the program a race condition. I would probably call it silliness.
  4. Use promises, use RxJS, and you wouldn't have design errors in your code.
</Rant>  

As always - would love to hear your opinion about this. As I always say, I might be completely wrong!

Connect with me on Twitter or LinkedIn to continue the discussion.

I'm an IT consultant, full stack developer, husband, and father. On my spare time I am contributing to Babylon.js WebGL game engine and other open source projects.

Berlin, Germany