I thought I won't ever need to handle synchronization problems and critical sections in JavaScript because it is single threaded. Well...
Problem
Multiple website sends data to multiple locally hosted pages which accesses the same piece of memory at the same time, causing a race condition.
Here's a simple code that I just wrote that will let two children compute a result and send it back to parent:
window.addEventListener("load", function() {
//threads analogy in JavaScript!
if (location.search.length) {
//receiver
var query = decodeURIComponent(location.search.slice(1));
var data = JSON.parse(query).value;
//handle data.
//start CRITICAL SECTION
localStorage.storage = +localStorage.storage + data;
//end CRITICAL SECTION
location.href = "about:blank"; //exit
} else {
//master
sum = document.getElementById("sum");
sum.innerText = localStorage.storage = "0";
window.addEventListener("storage", function() {
//data received from receiver
sum.innerText = localStorage.storage;
});
}
});
Multiple pages will calculate a number and send in back to the parent:
var frame = document.createElement("iframe");
frame.src = 'http://localhost:8080/master.html?{"value":1}'; //port 8080
document.body.appendChild(frame);
var n=0;
frame.addEventListener("load", function(){
if(n) document.body.removeChild(frame);
else n=1;
}
Since localStorage is shared between pages of the same domain, and all these pages are running on different threads, this literally causing a race condition, in JavaScript.
I tried creating 2 instances which each of them simultaneously and continuously send back a value of 1
10 times. The result I got at the end is always less than 20.
In C there is mutex to save our lives. How should I approach this problem in JavaScript where there is no locking mechanisms?
This graph might be easier to understand: