[javascript] Is JavaScript guaranteed to be single-threaded?

JavaScript is known to be single-threaded in all modern browser implementations, but is that specified in any standard or is it just by tradition? Is it totally safe to assume that JavaScript is always single-threaded?

This question is related to javascript concurrency

The answer is


Yes, although you can still suffer some of the issues of concurrent programming (mainly race conditions) when using any of the asynchronous APIs such as setInterval and xmlhttp callbacks.


Actually, a parent window can communicate with child or sibling windows or frames that have their own execution threads running.


No.

I'm going against the crowd here, but bear with me. A single JS script is intended to be effectively single threaded, but this doesn't mean that it can't be interpreted differently.

Let's say you have the following code...

var list = [];
for (var i = 0; i < 10000; i++) {
  list[i] = i * i;
}

This is written with the expectation that by the end of the loop, the list must have 10000 entries which are the index squared, but the VM could notice that each iteration of the loop does not affect the other, and reinterpret using two threads.

First thread

for (var i = 0; i < 5000; i++) {
  list[i] = i * i;
}

Second thread

for (var i = 5000; i < 10000; i++) {
  list[i] = i * i;
}

I'm simplifying here, because JS arrays are more complicated then dumb chunks of memory, but if these two scripts are able to add entries to the array in a thread-safe way, then by the time both are done executing it'll have the same result as the single-threaded version.

While I'm not aware of any VM detecting parallelizable code like this, it seems likely that it could come into existence in the future for JIT VMs, since it could offer more speed in some situations.

Taking this concept further, it's possible that code could be annotated to let the VM know what to convert to multi-threaded code.

// like "use strict" this enables certain features on compatible VMs.
"use parallel";

var list = [];

// This string, which has no effect on incompatible VMs, enables threading on
// this loop.
"parallel for";
for (var i = 0; i < 10000; i++) {
  list[i] = i * i;
}

Since Web Workers are coming to Javascript, it's unlikely that this... uglier system will ever come into existence, but I think it's safe to say Javascript is single-threaded by tradition.


Try to nest two setTimeout functions within each other and they will behave multithreaded (ie; the outer timer won't wait for the inner one to complete before executing its function).


I've tried @bobince's example with a slight modifications:

<html>
<head>
    <title>Test</title>
</head>
<body>
    <textarea id="log" rows="20" cols="40"></textarea>
    <br />
    <button id="act">Run</button>
    <script type="text/javascript">
        let l= document.getElementById('log');
        let b = document.getElementById('act');
        let s = 0;

        b.addEventListener('click', function() {
            l.value += 'click begin\n';

            s = 10;
            let s2 = s;

            alert('alert!');

            s = s + s2;

            l.value += 'click end\n';
            l.value += `result = ${s}, should be ${s2 + s2}\n`;
            l.value += '----------\n';
        });

        window.addEventListener('resize', function() {
            if (s === 10) {
                s = 5;
            }

            l.value+= 'resize\n';
        });
    </script>
</body>
</html>

So, when you press Run, close alert popup and do a "single thread", you should see something like this:

click begin
click end
result = 20, should be 20

But if you try to run this in Opera or Firefox stable on Windows and minimize/maximize window with alert popup on screen, then there will be something like this:

click begin
resize
click end
result = 15, should be 20

I don't want to say, that this is "multithreading", but some piece of code had executed in a wrong time with me not expecting this, and now I have a corrupted state. And better to know about this behavior.


@Bobince is providing a really opaque answer.

Riffing off of Már Örlygsson's answer, Javascript is always single-threaded because of this simple fact: Everything in Javascript is executed along a single timeline.

That is the strict definition of a single-threaded programming language.


I would say that the specification does not prevent someone from creating an engine that runs javascript on multiple threads, requiring the code to perform synchronization for accessing shared object state.

I think the single-threaded non-blocking paradigm came out of the need to run javascript in browsers where ui should never block.

Nodejs has followed the browsers' approach.

Rhino engine however, supports running js code in different threads. The executions cannot share context, but they can share scope. For this specific case the documentation states:

..."Rhino guarantees that accesses to properties of JavaScript objects are atomic across threads, but doesn't make any more guarantees for scripts executing in the same scope at the same time.If two scripts use the same scope simultaneously, the scripts are responsible for coordinating any accesses to shared variables."

From reading Rhino documentation I conclude that that it can be possible for someone to write a javascript api that also spawns new javascript threads, but the api would be rhino-specific (e.g. node can only spawn a new process).

I imagine that even for an engine that supports multiple threads in javascript there should be compatibility with scripts that do not consider multi-threading or blocking.

Concearning browsers and nodejs the way I see it is:

    1. Is all js code executed in a single thread? : Yes.
    1. Can js code cause other threads to run? : Yes.
    1. Can these threads mutate js execution context?: No. But they can (directly/indirectly(?)) append to the event queue from which listeners can mutate execution context. But don't be fooled, listeners run atomically on the main thread again.

So, in case of browsers and nodejs (and probably a lot of other engines) javascript is not multithreaded but the engines themselves are.


Update about web-workers:

The presence of web-workers justifies further that javascript can be multi-threaded, in the sense that someone can create code in javascript that will run on a separate thread.

However: web-workers do not curry the problems of traditional threads who can share execution context. Rules 2 and 3 above still apply, but this time the threaded code is created by the user (js code writer) in javascript.

The only thing to consider is the number of spawned threads, from an efficiency (and not concurrency) point of view. See below:

About thread safety:

The Worker interface spawns real OS-level threads, and mindful programmers may be concerned that concurrency can cause “interesting” effects in your code if you aren't careful.

However, since web workers have carefully controlled communication points with other threads, it's actually very hard to cause concurrency problems. There's no access to non-threadsafe components or the DOM. And you have to pass specific data in and out of a thread through serialized objects. So you have to work really hard to cause problems in your code.


P.S.

Besides theory, always be prepared about possible corner cases and bugs described on the accepted answer


JavaScript/ECMAScript is designed to live within a host environment. That is, JavaScript doesn't actually do anything unless the host environment decides to parse and execute a given script, and provide environment objects that let JavaScript actually be useful (such as the DOM in browsers).

I think a given function or script block will execute line-by-line and that is guaranteed for JavaScript. However, perhaps a host environment could execute multiple scripts at the same time. Or, a host environment could always provide an object that provides multi-threading. setTimeout and setInterval are examples, or at least pseudo-examples, of a host environment providing a way to do some concurrency (even if it's not exactly concurrency).


I'd say yes - because virtually all existing (at least all non-trivial) javascript code would break if a browser's javascript engine were to run it asynchronously.

Add to that the fact that HTML5 already specifies Web Workers (an explicit, standardized API for multi-threading javascript code) introducing multi-threading into the basic Javascript would be mostly pointless.

(Note to others commenters: Even though setTimeout/setInterval, HTTP-request onload events (XHR), and UI events (click, focus, etc.) provide a crude impression of multi-threadedness - they are still all executed along a single timeline - one at a time - so even if we don't know their execution order beforehand, there's no need to worry about external conditions changing during the execution of an event handler, timed function or XHR callback.)


Well, Chrome is multiprocess, and I think every process deals with its own Javascript code, but as far as the code knows, it is "single-threaded".

There is no support whatsoever in Javascript for multi-threading, at least not explicitly, so it does not make a difference.


Yes, although Internet Explorer 9 will compile your Javascript on a separate thread in preparation for execution on the main thread. This doesn't change anything for you as a programmer, though.