This is possible in case of variable a
being accessed by, say 2 web workers through a SharedArrayBuffer as well as some main script. The possibility is low, but it is possible that when the code is compiled to machine code, the web workers update the variable a
just in time so the conditions a==1
, a==2
and a==3
are satisfied.
This can be an example of race condition in multi-threaded environment provided by web workers and SharedArrayBuffer in JavaScript.
Here is the basic implementation of above:
main.js
// Main Thread
const worker = new Worker('worker.js')
const modifiers = [new Worker('modifier.js'), new Worker('modifier.js')] // Let's use 2 workers
const sab = new SharedArrayBuffer(1)
modifiers.forEach(m => m.postMessage(sab))
worker.postMessage(sab)
worker.js
let array
Object.defineProperty(self, 'a', {
get() {
return array[0]
}
});
addEventListener('message', ({data}) => {
array = new Uint8Array(data)
let count = 0
do {
var res = a == 1 && a == 2 && a == 3
++count
} while(res == false) // just for clarity. !res is fine
console.log(`It happened after ${count} iterations`)
console.log('You should\'ve never seen this')
})
modifier.js
addEventListener('message' , ({data}) => {
setInterval( () => {
new Uint8Array(data)[0] = Math.floor(Math.random()*3) + 1
})
})
On my MacBook Air, it happens after around 10 billion iterations on the first attempt:
Second attempt:
As I said, the chances will be low, but given enough time, it'll hit the condition.
Tip: If it takes too long on your system. Try only a == 1 && a == 2
and change Math.random()*3
to Math.random()*2
. Adding more and more to list drops the chance of hitting.
==
when you mean===
, have a coding standard that bans non-ASCII variable names, and have a linting process which enforces the previous two morals. – Jesse C. Slicer