Greasy Fork is available in English.

Обсуждения » Обсуждение сайта Greasy Fork

Multithreading concurrent writes to localStorage?

I was wondering, when using the browser's localstorage, I'm worried that having 2+ tabs running the same script both using the localstorage may break the values stored in it.

Is javascript multithreaded on the whole browser? Meaning two tabs are running the same script, and that it actually runs the script mid-run of another script?

For example, it does this:
Create a localstorage {"test": "0"} if it hadn't already.
When a page is opened, executes this:

let TestNumber = parseInt(localStorage.getItem("test"));
TestNumber++
localStorage.setItem("test", TestNumber);

If I happened to open 2 tabs at once and as the first time, can it causes both of them to do 0+1 = 1, sets it to 1 on each, and REPLACE the other script's save data, resulting it to be 1 as the end result instead of doing one at a time (single-threaded) where it did 0+1 = 1, then on the next tab, since its value is now 1, would do 1+1 = 2?
and have "test": "2"?

§
Создано: 19.08.2022
Отредактировано: 19.08.2022

Here is a working code, I tried to reproduce it, but wasn't able to make it run both code at once.

// ==UserScript==
// @name     concurrent test
// @namespace    any site
// @version  1
// @description  Add +1 every site you visit on the localstorage
// @grant    none
// @include  *
// ==/UserScript==

(function() {
 let a = 0
 if (localStorage.getItem('test')==null) {
  localStorage.setItem("test", "0");
 }
 a = parseInt(localStorage.getItem('test'), 10);
 a++
 localStorage.setItem("test", a);

 console.log("testing, value of a: " + a.toString(10));
})();
§
Создано: 19.08.2022
Отредактировано: 19.08.2022

(function() {
let a = 0
if (localStorage.getItem('test')==null) {
localStorage.setItem("test", a);
}
a = parseInt(localStorage.getItem('test'));
a += 1
localStorage.setItem("test", a);

console.log("testing, value of a: " + a.toString());
})();


The code above adds +1 every time it runs on the same page, if you run it 5 times on the same page the result will be 5, but if you test it on another page the result will be 0 then 1 and will gradually increase +1 every time for the same page only.

So, I think localStorage can't be accessed across websites for security reasons.
Just as here https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage says "The localStorage read-only property of the window interface allows you to access a Storage object for the Document's origin;"

That's why I prefer much more to use the tampermonkey storage too

// ==UserScript==
// @name test
// @namespace https://greasyfork.org/en/users/670188-hacker09?sort=daily_installs
// @version 1
// @description test
// @author hacker09
// @include *
// @run-at document-end
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==

(function() {
'use strict';
let a = 0
if (localStorage.getItem('test')==null) {
GM_setValue("test", a);
}
a = GM_getValue('test');
a += 1
GM_setValue("test", a);

console.log("testing, value of a: " + GM_getValue('test'));
})();

§
Создано: 16.12.2023
Отредактировано: 16.12.2023

I realize this bug do in fact exists when doing multithreading is called a race condition and that example exactly matches what wikipedia have shown to me.

I realize this bug do in fact exists when doing multithreading is called a race condition and that example exactly matches what wikipedia have shown to me.

I don't think it is easy to explain to you the whole concept of what it describes.

That is not talking about the multiple tabs in a browser. Multithreading is talking about the coding in the same codespace.

If I happened to open 2 tabs at once and as the first time, can it causes both of them to do 0+1 = 1, sets it to 1 on each, and REPLACE the other script's save data, resulting it to be 1 as the end result instead of doing one at a time (single-threaded) where it did 0+1 = 1, then on the next tab, since its value is now 1, would do 1+1 = 2?

The answer is no. You don't need to worry it. JavaScript is slow.

In Javascript, there are concepts as "macrotasks" and "microtasks".

Again, it is out of the discussion here. Learn by yourself.

let TestNumber = parseInt(localStorage.getItem("test"));
TestNumber++
localStorage.setItem("test", TestNumber);

In your concern, the three lines are in the same microtask. Once it is done, the another tab will execute its tasks.

localStorage's getItem and setItem are synchronous.

I realize this bug do in fact exists when doing multithreading is called a race condition and that example exactly matches what wikipedia have shown to me.

I don't think it is easy to explain to you the whole concept of what it describes.

That is not talking about the multiple tabs in a browser. Multithreading is talking about the coding in the same codespace.

If I happened to open 2 tabs at once and as the first time, can it causes both of them to do 0+1 = 1, sets it to 1 on each, and REPLACE the other script's save data, resulting it to be 1 as the end result instead of doing one at a time (single-threaded) where it did 0+1 = 1, then on the next tab, since its value is now 1, would do 1+1 = 2?

The answer is no. You don't need to worry it. JavaScript is slow.

In Javascript, there are concepts as "macrotasks" and "microtasks".

Again, it is out of the discussion here. Learn by yourself.

let TestNumber = parseInt(localStorage.getItem("test"));
TestNumber++
localStorage.setItem("test", TestNumber);

In your concern, the three lines are in the same microtask. Once it is done, the another tab will execute its tasks.

localStorage's getItem and setItem are synchronous.

Thanks for correcting me, so tab-based race conditions cannot happen.

Ответить

Войдите, чтобы ответить.