Bevezetés a megosztott memóriába a JavaScript-ben
Megosztott memória A JavaScript egy fejlett jellemzője, hogy a szálak (egy folyamat egyidejűleg végrehajtott részei) kihasználhatják. A memóriaeszközök megosztása nem baj, hogy frissített adatokat továbbítanak a szálak között és az összes szál ugyanazokat az adatokat férhet hozzá és frissítheti a megosztott memóriában.
Nem hangzik szép? Hát majdnem. Ebben a bejegyzésben látni fogjuk hogyan használhatja a megosztott memóriát a JavaScript-ben és hogyan kell eldönteni, hogy valóban ezt akarja-e tenni.
A megosztott memória előnyei és hátrányai
Mi használjuk webmunkások nak nek szálak létrehozása a JavaScript-ben. A Web Workers API lehetővé teszi, hogy olyan munkamenetet hozzunk létre, amelyre fel lehet használni hajtsa végre a kódot a háttérben úgy, hogy a fő szál szabadon folytathassa a végrehajtását, esetleg feldolgozza az UI eseményeket, biztosítva az UI befagyasztását.
Munkavállalói szálak fusson a fő szálral és egymással párhuzamosan. A feladat különböző részeinek ilyen egyidejű végrehajtása időtakarékos. Gyorsabban befejezed, de saját problémákat is tartalmaz.
Győződjön meg róla, hogy minden szál megkapja a szükséges erőforrásokat és időben kommunikál egymással önmaga feladata, ahol egy baleset meglepő eredményt eredményezhet. Vagy ha az egyik szál változik az adatok, és egy másik azt olvassa ugyanabban az időben, mit gondol a másik szál? A frissített vagy a régi adatok?
A webmunkások azonban nem olyan könnyen felcsavarozhatók. Az üzeneteken keresztüli kommunikáció során az általuk küldött adatok nem eredeti, hanem másolat, azt jelenti, hogy nem részvény ugyanazokat az adatokat. Ők másolja át az adatok másolatát amikor szükség van.
De a megosztás gondoskodik, és több szál is szükség lehet ugyanazokra az adatokra egyidejűleg, és módosítani kell őket. Így, a megosztás megtiltása egy nagy no-no. Ez az, ahol a SharedArrayBuffer
az objektum a képbe kerül. Megenged minket bináris adatok megosztása több szál között.
A SharedArrayBuffer
tárgy
Ahelyett, hogy átmásolnánk az adatmásolatokat a szálak között, mi átmásolja a másolatokat SharedArrayBuffer
tárgy. A SharedArrayBuffer
tárgy arra a memóriára mutat, ahol az adatok mentésre kerülnek.
Tehát még akkor is, ha a másolatok SharedArrayBuffer
a szálak között kerülnek átadásra mindez ugyanarra a memóriára mutat az eredeti adatok mentése. A szálak így megtekintheti és frissítheti az adatokat ugyanabban a memóriában.
Webes munkások nélkül megosztott memória
Hogy megnézzük, hogyan működik a webmunkás megosztott memória használata nélkül, mi hozzon létre egy munkavállaló szálat és adjon át néhány adatot.
A index.html
a fájl a fő parancsfájl belül a címke, ahogy azt az alábbiakban láthatja:
const w = új munkás ('worker.js'); var n = 9; w.postMessage (n);
A worker.js
a fájl a munkavállaló script:
onmessage = (e) => console.group ('[munkavállaló]); console.log ('A főszálból kapott adatok:% i', e.data); console.groupEnd ();
A fenti kód használatával a következőket kapjuk kimenet a konzolban:
[munkavállaló] A fő szálból kapott adatok: 9
A fent említett részleteket a webes munkatársaknál olvashatod a kódrészlet teljes kódmódosításához.
Most tartsa szem előtt, hogy az adatok a szálak között oda-vissza használni a postMessage ()
eljárás. Az adatok a másik oldalon a üzenet
eseménykezelő, az esemény értéke adat
ingatlan.
Most, ha mi módosítsa az adatokat jelenik meg frissítve a fogadó végén? Lássuk:
const w = új munkás ('worker.js'); var n = 9; w.postMessage (n); n = 1;
Ahogy az várható volt, a adatoknak nem frissítve:
[munkavállaló] A fő szálból kapott adatok: 9
Miért lenne ez egyébként? ez csak egy klón lett elküldve a munkavállalónak a fő szkriptből.
Webes munkások val vel megosztott memória
Most már használja a SharedArrayBuffer
tárgy ugyanabban a példában. Újat hozhatunk létre SharedArrayBuffer
például használni a új
kulcsszó. A konstruktor egy paramétert vesz fel; egy hossza bájtban, meghatározza a puffer méretét.
const w = új munkás ('worker.js'); buff = new SharedArrayBuffer (1); var arr = új Int8Array (buff); / * beállítási adatok * / arr [0] = 9; / * a puffer (másolat) elküldése a * / w.postMessage (buff) munkatársnak;
Ne feledje, hogy a SharedArrayBuffer
tárgy csak egy megosztott memóriaterületet képvisel. Nak nek a bináris adatok megtekintése és módosítása, megfelelő adatstruktúrát kell használnunk (a TypedArray
vagy a DataView
tárgy).
Ban,-ben index.html
a fenti fájl, egy új SharedArrayBuffer
csak egy bájt hosszúságú. Ezután egy új Int8Array
, ami egyfajta TypedArray
az objektumokhoz állítsa be az adatokat “9” a megadott bájtterületen.
onmessage = (e) => var arr = új Int8Array (e.data); console.group ( '[munkás]'); console.log ('A főszálból kapott adatok:% i', arr [0]); console.groupEnd ();
Int8Array
a munkavállalóban is használják nézze meg az adatokat a pufferben.
A a várt érték megjelenik a konzolban a munkásszálból, amit pontosan akartunk:
[munkavállaló] A fő szálból kapott adatok: 9
Most, hadd frissítse az adatokat a fő szálban hogy megtudja, hogy a változás tükröződik-e a munkavállalóban.
const w = új munkás ('worker.js'), buff = new SharedArrayBuffer (1); var arr = új Int8Array (buff); / * beállítási adatok * / arr [0] = 9; / * a puffer (másolat) elküldése a * / w.postMessage (buff) munkatársnak; / * az adatok módosítása * / arr [0] = 1;
És ahogy az alábbiakban látható, a frissítés tükrözi a munkavállaló belsejében!
[munkavállaló] A fő szálból kapott adatok: 1
De a kód is kell fordulni: amikor az érték a munkavállalóban először változik, akkor frissíteni kell ha a fő szálból nyomtat.
Ebben az esetben kódunk így néz ki:
onmessage = (e) => var arr = új Int8Array (e.data); console.group ( '[munkás]'); console.log ('A főszálból kapott adatok:% i', arr [0]); console.groupEnd (); / * az adatok módosítása * / arr [0] = 7; / * kiküldetés a fő szálra * / postMessage (");
A az adatok megváltoznak a munkavállalóban és egy üres üzenet kerül a fő szálra jelzi, hogy a pufferben lévő adatok megváltoztak, és készen áll a fő szál kiadására.
const w = új munkás ('worker.js'), buff = new SharedArrayBuffer (1); var arr = új Int8Array (buff); / * beállítási adatok * / arr [0] = 9; / * a puffer (másolat) elküldése a * / w.postMessage (buff) munkatársnak; / * az adatok módosítása * / arr [0] = 1; / * az adatok kinyomtatása a munkavállaló módosítása után * / w.onmessage = (e) => console.group ('[main]'); console.log ('Frissített adatok a munkavállalói szálból:% i', arr [0]); console.groupEnd ();
És ez is működik! A pufferben lévő adatok megegyeznek a munkavállalón belüli adatokkal.
[munkás] A fő szálból kapott adatok: 1 [fő] A munkavállalói szálból kapott frissített adatok: 7
Az érték mindkét esetben naprakész; mind a fő, mind a munkavállaló szálai ugyanazokat az adatokat tekintik meg és változtatják meg.
Végső szavak
Mint korábban említettem, a megosztott memória használata a JavaScript-ben nem nélkülözhetetlen. A fejlesztők feladata annak biztosítása, hogy a a végrehajtás sorrendje az előre jelzett módon történik és két szál nem versenyez, hogy ugyanazokat az adatokat kapja, mert senki sem tudja, ki fogja venni a trófeát.
Ha jobban érdekli a megosztott memória, nézd meg a dokumentációt atomfegyvert
tárgy. A Az atomobjektum segíthet a nehézségek egy részében, a megosztott memóriából történő olvasás / írás kiszámíthatatlanságának csökkentésével.