The ECMAScript specification defines the Atomics object in the section 24.4.
Among all the global objects this is the more obscure for me since I didn't know about its existence until I didn't read its specification, and also Google hasn't many references to it (or maybe the name is too much generic and everything gets submerged?).
According its official definition
The Atomics object provides functions that operate indivisibly (atomically) on shared memory array cells as well as functions that let agents wait for and dispatch primitive events
So it has the shape of an object with a number of methods to handle low-level memory and regulate the access to it. And also its public interface makes me suppose it. But what's the actual use of such object for the end-user? Why is it public? Are there some examples where it can be useful?
Thank you
If you have some complex computation you may need WebWorkers, in order to your main script may continue his work while heavy things are done in parallel.
Problem that Atomics solve is how WebVorkers can comunicate between each other (easy, fast and relaible). You can read about ArrayBuffer, SharedArrayBuffer, Atomics and how you can use them for your benifits here.
You shouldn't bother about it if:
You may need it if:
WebAssembly
orwebgl
and you want to optimize performanceThank you Pavlo Mur and Simon Paris for yours answers!
Atomics are for synchronising WebWorkers that share memory. They cause memory access into a SharedArrayBuffer to be done in a thread safe way. Shared memory makes multithreading much more useful because:
Example:
SharedArrayBuffer was enabled previously on major browsers, but after the Spectre incident it was disabled because shared memory allows implementation of nanosecond-precision timers, which allow exploitation of spectre.
In order to make it safe, browsers need to run pages a separate process for each domain. Chrome started doing this in version 67 and shared memory was re-enabled in version 68.
Atomic operation is "everything or nothing" group of smaller operations.
Let's have a look at
i++
is actually evaluated with 3 stepsi
valuei
by 1What happens if you have 2 threads doing the same operation? they can both read the same value
1
and increment it at the exact same time.But this and Javascript, isn't it's single threaded?
Yes! JavaScript indeed single threads but browsers / node allows today usage of several JavaScript runtimes in parallel (Worker Threads, Web Workers).
Chrome and Node (v8 based) creates Isolate for each thread, which they all run in their own
context
.And the only way the can
share memory
is viaArrayBuffer
/SharedArrayBuffer
What will be the output of the next program?
Run with node > =10
node --experimental_worker example.js
The output might be
2,500,000
but we don't know that and in most of the cases it won't be 2.5M, actually, the chance that you'll get the same output twice is pretty low, and as programmers we surely don't like code that we have no idea how it's going to end.This is an example for race condition, where n threads race each other and not synced in any way.
Here comes the
Atomic
operation, that allows us to make arithmetic operations from start to end.Let's change the program a bit and now run:
Now the output will always be
2,500,000
Bonus, Mutex using Atomics
Sometimes, we wish to an operation that only 1 thread can access at the same time, let's have a look at the next class
Now, you need to allocate
SharedArrayBuffer
and share them between all the threads and see that each time only 1 threads go inside thecritical section
Run with node > 10
node --experimental_worker example.js
In addition to what Arseniy-II and Simon Paris stated, Atomics are also handy when you embed JavaScript engine into some host application (to enable scripting in it). Then one can directly access shared memory from different concurent threads simultaneously, both from JS and from C/C++ or whatever language your host application is written, without involving JavaScript API for access on C/C++/OtherLanguage side.