Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Since JavaScript is single-threaded, how are web workers in HTML5 doing multi-threading?

I've been reading about web workers in HTML5, but I know JavaScript is single-threaded.

My question is:

How are web workers doing multi-threaded work then? or how are they simulating it if it's not truely multi-threaded? Doesn't seem clear to me here.

like image 817
James Drinkard Avatar asked Mar 14 '12 18:03

James Drinkard


People also ask

Do web workers make JavaScript multithreaded?

Web workers let you write true multi-threaded JavaScript, meaning different bits of your code can be running at the same time. Without web workers, all code runs on the UI thread. Even things that seem multi-threaded, like ajax callbacks, setTimeout and setInterval , are actually single threaded.

Are web workers multi-threaded?

Web workers don't make javascript multi-threaded in any way that it wasn't before, think about it like this: you're essentially starting another single-threaded process and communicating with it, like you would be able to in node. js for example.

Is JavaScript single threaded or multithreaded?

JavaScript is a single-threaded language because while running code on a single thread, it can be really easy to implement as we don't have to deal with the complicated scenarios that arise in the multi-threaded environment like deadlock. Since, JavaScript is a single-threaded language, it is synchronous in nature.


2 Answers

As several comments have already pointed out, Workers really are multi-threaded.

Some points which may help clarify your thinking:

  • JavaScript is a language, it doesn't define a threading model, it's not necessarily single threaded
  • Most browsers have historically been single threaded (though that is changing rapidly: IE, Chrome, Firefox), and most JavaScript implementations occur in browsers
  • Web Workers are not part of JavaScript, they are a browser feature which can be accessed through JavaScript
like image 150
robertc Avatar answered Oct 09 '22 08:10

robertc


A bit late, but I just asked myself the same question and I came up with the following answer:
Javascript in browsers is always single-threaded, and a fundamental consequence is that "concurrent" access to variables (the principal headache of multithreaded programming) is actually not concurrent; this is true with the exception of webworkers, which are actually run in separate threads and concurrent access to variables must be dealt with in a somewhat explicit way.

I am not a JavaScript ninja, but I too was convinced that JavaScript in browser is provided as a single threaded process, without paying much attention to whether it was true or to the rationale behind this belief.
A simple fact that supports this assumption is that when programming in JavaScript you don't have to care about concurrent access to shared variables. Every developer, without even thinking of the problem, writes code as if every access to a variable is consistent.
In other words, you don't need to worry about the so called Memory model.

Actually there is no need of looking at WebWorkers to involve parallel processing in JavaScript. Think of an (asynchronous) AJAX request. And think how carelessly you would handle concurrent access to variables:

var counter = 0;  function asyncAddCounter() {   var xhttp = new XMLHttpRequest();   xhttp.onreadystatechange = function() {     if (this.readyState == 4) {       counter++;     }   };   xhttp.open("GET", "/a/remote/resource", true);   xhttp.send(); }  asyncAddCounter(); counter++; 

What is the value of counter at the end of the process? It is 2. It doesn't matter that it is read and written "concurrently", it will never result in a 1. This means that access to counter is always consistent. If two threads where really accessing the value concurrently, they both could start off by reading 0 and both write 1 in the end.

In browsers, the actual data-fetching of a remote resource is hidden to the developer, and its inner workings are outside the scope of the JavaScript API (what the browser let's you control in terms of JavaScript instructions). As far as the developer is concerned, the result of the network request is processed by the main thread.
In short, the actual carrying out of the request is not visible, but the invocation of the callback (handling the result by custom JavaScript code) is executed by the main thread.
Possibly, if it wasn't for the webworkers, the term "multithreading" wouldn't ever enter the Javascript world.

The execution of the request and the asynchronous invocation of the callback is actually achieved by using event loops, not multithreading. This is true for several browsers and obviously for Node.js. The following are some references, in some cases a bit obsolete, but I guess that the main idea is still retained nowadays.

  • Firefox: Concurrency model and Event Loop - JavaScript | MDN
  • Chrome uses libevent in certain OS.
  • IE: Understanding the Event Model (Internet Explorer)

This fact is the reason why JavaScript is said to be Event-driven but not multithreaded.
Notice that JavaScript thus allows for asynchronous idioms, but not parallel execution of JavaScript code (outside webworkers). The term asynchronous just denotes the fact that the result of two instructions might be processed in scrambled order.

As for WebWorkers, they are JavaScript APIs that give a developer control over a multithreaded process.
As such, they provide explicit ways to handle concurrent access to shared memory (read and write values in different threads), and this is done, among the others, in the following ways:

  • you push data to a web worker (which means that the new thread reads data) by structured clone: The structured clone algorithm - Web APIs | MDN. Essentially there is no "shared" variable, instead the new thread is given a fresh copy of the object.
  • you push data to a web worker by transferring ownership of the value: Transferable - Web APIs | MDN. This means that the just one thread can read its value at any time.
  • as for the results returned by the web workers (how they "write"), the main thread access the results when prompted to do so (for instance with the instruction thisWorker.onmessage = function(e) {console.log('Message ' + e.data + ' received from worker');}). It must be by means of the usual Event Loop, I must suppose.
  • the main thread and the web worker access a truly shared memory, the SharedArrayBuffer, which is thread-safely accessed using the Atomic functions. I found this clearly exposed in this article: JavaScript: From Workers to Shared Memory
  • note: webworkers cannot access the DOM, which is truly shared!
like image 44
Antonio Avatar answered Oct 09 '22 09:10

Antonio