Ceci est possible en cas d' a
accès à une variable par, disons, 2 travailleurs Web via un SharedArrayBuffer ainsi que certains scripts principaux. La possibilité est faible, mais il est possible que lorsque le code est compilé en code machine, les travailleurs Web mettent à jour la variable a
juste à temps pour que les conditions a==1
, a==2
eta==3
sont satisfaits.
Cela peut être un exemple de condition de concurrence critique dans un environnement multithread fourni par les travailleurs Web et SharedArrayBuffer en JavaScript.
Voici l'implémentation de base de ci-dessus:
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)
travailleur.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
})
})
Sur mon MacBook Air, cela se produit après environ 10 milliards d'itérations lors de la première tentative:
Deuxième essai:
Comme je l'ai dit, les chances seront faibles, mais avec suffisamment de temps, cela atteindra la situation.
Astuce: si cela prend trop de temps sur votre système. Essayez uniquement a == 1 && a == 2
et passez Math.random()*3
à Math.random()*2
. Ajouter de plus en plus à la liste diminue les chances de frapper.