Uvod u zajedničku memoriju u JavaScriptu
Zajednička memorija je napredna značajka JavaScripta, da niti (istodobno izvršeni dijelovi procesa) mogu utjecati. Dijeljenje memorijskih sredstava nema problema s prosljeđivanjem ažuriranih podataka između niti i sve niti mogu pristupiti i ažurirati iste podatke u zajedničkoj memoriji.
Zar to ne zvuči divno? Pa, gotovo. U ovom postu vidjet ćemo kako koristiti zajedničku memoriju u JavaScriptu i kako odlučiti je li to ono što stvarno želite učiniti.
Prednosti i nedostaci zajedničke memorije
Koristimo web radnici do stvorite niti u JavaScriptu. API API-ja za web-radnike omogućuje nam da stvorimo radne niti kojima se može koristiti izvršite kod u pozadini tako da je glavna nit slobodna da nastavi s izvršavanjem, moguće obrade UI događaja, osiguravajući da nema zamrzavanja korisničkog sučelja.
Radni konci izvoditi istodobno s glavnim navojem i međusobno. Takvo istovremeno izvršavanje različitih dijelova zadatka štedi vrijeme. Završavate brže, ali ima i svoje probleme.
Osigurati da svaka nit dobiva potrebne resurse i komunicira međusobno na vrijeme je zadatak sam po sebi, gdje nesreća može rezultirati iznenađujućim ishodom. Ili ako jedna nit mijenja podatke, a druga je čita u isto vrijeme, što mislite da će druga nit vidjeti? Ažurirani ili stari podaci?
Međutim, web radnici nisu tako lako zajebati. Tijekom njihove komunikacije putem poruka, podaci koje šalju jedan drugome su ne original, nego kopija, što znači da ne znaju udio isti podaci. Oni međusobno prosljeđujte kopije podataka kada je potrebno.
No dijeljenje je brižno, a više niti bi moglo istodobno gledati iste podatke i mijenjati ih. Tako, zabrana dijeljenja je velika ne-ne. Ovo je mjesto gdje SharedArrayBuffer
objekt dolazi u sliku. Pustit će nas dijelite binarne podatke između više niti.
SharedArrayBuffer
objekt
Umjesto prosljeđivanja kopija podataka između niti, mi kopije SharedArrayBuffer
objekt. SharedArrayBuffer
objekt pokazuje na memoriju u kojoj su podaci spremljeni.
Dakle, čak i kada kopije SharedArrayBuffer
su prošli između niti, oni sve će i dalje ukazivati na istu memoriju gdje su izvorni podaci spremljeni. Niti, dakle, mogu pregledajte i ažurirajte podatke u istoj memoriji.
Web radnici bez zajedničku memoriju
Da bismo vidjeli kako web radnik radi bez zajedničke memorije, stvorite radnu nit i proslijediti mu neke podatke.
index.html
Datoteka sadrži glavna skripta unutar a kao što možete vidjeti u nastavku:
const w = novi radnik ('worker.js'); var n = 9; w.postMessage (n);
worker.js
datoteka nosi oznaku radnička skripta:
onmessage = (e) => console.group ('[radnik]'); console.log ('Podaci primljeni iz glavne teme:% i', e.data); console.groupEnd ();
Koristeći gornji kod dobivamo sljedeće izlaz u konzoli:
[radnik] Podaci primljeni iz glavne niti: 9
Moju gore navedenu poruku možete pročitati na web radnicima radi potpunog objašnjenja koda gore navedenih isječaka.
Za sada, imajte na umu da su podaci poslane natrag i naprijed između niti koristiti postMessage ()
metoda. Podaci su na drugu stranu poruka
rukovatelj događajima, kao vrijednost događaja podaci
svojstvo.
Sada, ako mi promijenite podatke će se prikazati ažuriran na kraju primitka? Da vidimo:
const w = novi radnik ('worker.js'); var n = 9; w.postMessage (n); n = 1;
Kao što se i očekivalo podataka ima ne ažurirano:
[radnik] Podaci primljeni iz glavne niti: 9
Zašto bi to uopće bilo? to je samo klon poslan radniku iz glavne skripte.
Web radnici s zajedničku memoriju
Sada ćemo koristiti SharedArrayBuffer
objekt u istom primjeru. Možemo stvoriti novo SharedArrayBuffer
na primjer koristiti novi
ključna riječ. Konstruktor uzima jedan parametar; vrijednost duljine u bajtovima, određivanje veličine međuspremnika.
const w = novi radnik ('worker.js'); buff = new SharedArrayBuffer (1); var arr = novi Int8Array (buff); / * postavljanje podataka * / arr [0] = 9; / * slanje bafera (kopija) radniku * / w.postMessage (buff);
Imajte na umu da a SharedArrayBuffer
objekt predstavlja samo dijeljeno memorijsko područje. Do vidjeti i promijeniti binarne podatke, trebamo koristiti odgovarajuću strukturu podataka (a TypedArray
ili a DataView
objekt).
U index.html
iznad, novi SharedArrayBuffer
je stvoren, s samo jednom bajtnom duljinom. Zatim, novi Int8Array
, koja je jedna vrsta TypedArray
objekata postavite podatke na “9” u predviđenom bajtnom prostoru.
onmessage = (e) => var arr = novi Int8Array (e.data); console.group ( "[radnik]); console.log ('Podaci primljeni iz glavne teme:% i', arr [0]); console.groupEnd ();
Int8Array
se također koristi u radniku, na prikaz podataka u međuspremniku.
očekivana vrijednost pojavljuje se u konzoli iz radničke niti, što je upravo ono što smo htjeli:
[radnik] Podaci primljeni iz glavne niti: 9
Sada, hajde ažurirati podatke u glavnoj niti kako bi se vidjelo da li se promjena odražava na radnika.
const w = novi radnik ('worker.js'), buff = new SharedArrayBuffer (1); var arr = novi Int8Array (buff); / * postavljanje podataka * / arr [0] = 9; / * slanje bafera (kopija) radniku * / w.postMessage (buff); / * mijenjanje podataka * / arr [0] = 1;
I, kao što možete vidjeti u nastavku, ažuriranje ne odražava unutar radnika!
[radnik] Podaci primljeni iz glavne niti: 1
Ali, i kod treba raditi obrnuto: kada se vrijednost u radniku prvo mijenja također treba ažurirati kada se ispisuje iz glavne niti.
U ovom slučaju naš kôd izgleda ovako:
onmessage = (e) => var arr = novi Int8Array (e.data); console.group ( "[radnik]); console.log ('Podaci primljeni iz glavne teme:% i', arr [0]); console.groupEnd (); / * mijenjanje podataka * / arr [0] = 7; / * slanje na glavni thread * / postMessage (");
podaci se mijenjaju u radniku i jedan prazna poruka je postavljena na glavnu nit signalizira da su podaci u međuspremniku promijenjeni i spremni su za izlaz glavne niti.
const w = novi radnik ('worker.js'), buff = new SharedArrayBuffer (1); var arr = novi Int8Array (buff); / * postavljanje podataka * / arr [0] = 9; / * slanje bafera (kopija) radniku * / w.postMessage (buff); / * mijenjanje podataka * / arr [0] = 1; / * ispis podataka nakon što ga je radnik promijenio * / w.onmessage = (e) => console.group ('[main]'); console.log ('Ažurirani podaci primljeni iz radnog niza:% i', arr [0]); console.groupEnd ();
I to također djeluje! Podaci u međuspremniku su isti kao podaci unutar radnika.
[radnik] Podaci primljeni iz glavne teme: 1 [glavni] Ažurirani podaci primljeni iz radničke niti: 7
Vrijednost pojavljuje se ažurirano u oba slučaja; i glavna i radna nit pregledavaju i mijenjaju iste podatke.
Završne riječi
Kao što sam već spomenuo, korištenje zajedničke memorije u JavaScriptu nije bez mana. To je do developera kako bi se osiguralo da slijed izvršenja se događa kako je predviđeno i niti dvije niti se ne natječu da dobiju iste podatke jer nitko ne zna tko će uzeti trofej.
Ako ste zainteresirani za zajedničku memoriju više, pogledajte dokumentaciju Atomistika
objekt. Atomics objekt može vam pomoći s nekim od teškoća, smanjenjem nepredvidive prirode čitanja / pisanja iz zajedničke memorije.