Laman » Pengekodan » Pengenalan kepada Memori Dikongsi dalam JavaScript

    Pengenalan kepada Memori Dikongsi dalam JavaScript

    Memori dikongsi adalah ciri canggih JavaScript, bahawa benang-benang (bahagian-bahagian proses yang dijalankan secara serentak) boleh memanfaatkan. Perkongsian memori bermakna tidak mempunyai masalah untuk lulus data dikemas kini antara benang dan semua benang boleh mengakses dan mengemas kini data yang sama dalam ingatan yang dikongsi.

    Bukankah bunyi itu indah? Nah, hampir. Dalam siaran ini, kita akan lihat cara menggunakan memori yang dikongsi dalam JavaScript dan bagaimana untuk menentukan sama ada ini yang anda mahu lakukan.

    Kelebihan & kekurangan memori dikongsi

    Kami guna pekerja web kepada buat benang dalam JavaScript. API Pekerja Web membolehkan kami membuat benang pekerja yang boleh digunakan laksanakan kod di latar belakang supaya benang utama bebas untuk meneruskan pelaksanaannya, mungkin memproses acara UI, memastikan tidak membekukan UI.

    Benang pekerja berjalan serentak dengan benang utama dan satu sama lain. Pelaksanaan serentak seperti bahagian yang berbeza dari tugas adalah menjimatkan masa. Anda selesai dengan lebih cepat, tetapi ia juga mempunyai masalah sendiri.

    Memastikan setiap benang mendapat sumber yang diperlukan dan berkomunikasi dengan satu sama lain secara tepat pada masanya adalah tugas dalam dirinya sendiri, di mana kecelakaan boleh mengakibatkan hasil yang mengejutkan. Atau jika satu benang sedang berubah data dan satu lagi sedang membacanya pada masa yang sama, apa yang anda fikir benang yang lain akan melihat? Data yang dikemas kini atau lama?

    Walau bagaimanapun, pekerja web tidak begitu mudah untuk mengawal. Semasa komunikasi mereka menggunakan mesej, data yang mereka saling kirimkan adalah bukan asal tetapi salinannya, bermakna mereka tidak bahagian data yang sama. Mereka lulus salinan data antara satu sama lain apabila diperlukan.

    Tetapi perkongsian adalah peduli, dan beberapa benang mungkin juga perlu melihat data yang sama pada masa yang sama dan mengubahnya. Jadi, melarang perkongsian adalah no-no besar. Ini adalah di mana SharedArrayBuffer objek masuk ke dalam gambar. Ia akan membiarkan kami berkongsi data binari antara berbilang benang.

    The SharedArrayBuffer objek

    Daripada melewatkan salinan data antara benang, kita lulus salinan SharedArrayBuffer objek. A SharedArrayBuffer objek menunjuk ke ingatan di mana data disimpan.

    Jadi, walaupun ketika salinan SharedArrayBuffer diluluskan di antara benang, mereka semua masih akan menunjukkan ingatan yang sama di mana data asal disimpan. Benang, dengan itu, boleh melihat dan mengemas kini data dalam memori yang sama.

    Pekerja web tanpa memori yang dikongsi

    Untuk melihat bagaimana pekerja web berfungsi tanpa menggunakan memori yang dikongsi, kami membuat benang pekerja dan lulus beberapa data kepadanya.

    The index.html fail memegang skrip utama di dalam a tag, kerana anda dapat melihatnya di bawah:

     const w = Pekerja baru ('worker.js'); var n = 9; w.postMessage (n); 

    The pekerja.js fail membawa skrip pekerja:

     onmessage = (e) => console.group ('[worker]'); console.log ('Data diterima dari thread utama:% i', e.data); console.groupEnd ();  

    Menggunakan kod di atas, kami mendapat yang berikut output dalam konsol:

     [pekerja] Data diterima dari benang utama: 9 

    Anda boleh membaca catatan saya yang disebutkan di atas pada pekerja web untuk penjelasan kod penuh tentang coretan di atas.

    Buat masa ini, perlu diingat bahawa data adalah dihantar bolak-balik antara benang menggunakan postMessage () kaedah. Data tersebut adalah diterima di pihak lain oleh mesej Pengurus acara, sebagai nilai acara itu data harta.

    Sekarang, jika kita menukar data adakah ia akan dikemas kini pada akhir penerimaan? Mari lihat:

     const w = Pekerja baru ('worker.js'); var n = 9; w.postMessage (n); n = 1; 

    Seperti yang dijangka, data telah tidak telah dikemas kini:

     [pekerja] Data diterima dari benang utama: 9 

    Kenapa pula? Ia hanya satu klon yang dihantar kepada pekerja dari skrip utama.

    Pekerja web dengan memori yang dikongsi

    Sekarang, kita akan menggunakan SharedArrayBuffer objek dalam contoh yang sama. Kita boleh buat yang baru SharedArrayBuffer contoh oleh menggunakan baru kata kunci. Pembina mengambil satu parameter; a nilai panjang dalam bait, menyatakan saiz penampan.

     const w = Pekerja baru ('worker.js'); buff = SharedArrayBuffer baru (1); var arr = baru Int8Array (buff); / * setting data * / arr [0] = 9; / * menghantar buffer (copy) kepada pekerja * / w.postMessage (buff); 

    Perhatikan bahawa a SharedArrayBuffer objek hanya mewakili kawasan memori yang dikongsi. Untuk melihat dan menukar data binari, kita perlu menggunakan struktur data yang sesuai (a TypedArray atau a DataView objek).

    Di dalam index.html fail di atas, yang baru SharedArrayBuffer dicipta, dengan hanya satu-bait panjang. Kemudian, yang baru Int8Array, yang merupakan satu jenis TypedArray objek, digunakan untuk tetapkan data kepada “9” dalam ruang niat yang disediakan.

     onmessage = (e) => var arr = baru Int8Array (e.data); console.group ('[pekerja]'); console.log ('Data diterima dari thread utama:% i', arr [0]); console.groupEnd ();  

    Int8Array juga digunakan dalam pekerja, untuk melihat data dalam penampan.

    The nilai dijangka muncul di konsol dari benang pekerja, yang sebenarnya adalah apa yang kita inginkan:

     [pekerja] Data diterima dari benang utama: 9 

    Sekarang, mari kemas kini data dalam benang utama untuk melihat sama ada perubahan itu tercermin dalam pekerja.

     const w = Pekerja baru ('worker.js'), buff = SharedArrayBuffer baru (1); var arr = baru Int8Array (buff); / * setting data * / arr [0] = 9; / * menghantar buffer (copy) kepada pekerja * / w.postMessage (buff); / * mengubah data * / arr [0] = 1;

    Dan, seperti yang anda lihat di bawah, kemas kini tidak mencerminkan di dalam pekerja!

     [pekerja] Data diterima dari benang utama: 1 

    Tetapi, kod itu juga perlu bekerja dengan cara yang lain: apabila nilai pada pekerja berubah pada mulanya, ia juga perlu dikemas kini apabila ia dicetak dari benang utama.

    Dalam kes ini, kod kami kelihatan seperti ini:

     onmessage = (e) => var arr = baru Int8Array (e.data); console.group ('[pekerja]'); console.log ('Data diterima dari thread utama:% i', arr [0]); console.groupEnd (); / * mengubah data * / arr [0] = 7; / * mengepos ke thread utama * / postMessage ("); 

    The data berubah di pekerja dan a mesej kosong dihantar ke benang utama memberi isyarat bahawa data dalam penampan telah berubah dan siap untuk benang utamanya akan dikeluarkan.

     const w = Pekerja baru ('worker.js'), buff = SharedArrayBuffer baru (1); var arr = baru Int8Array (buff); / * setting data * / arr [0] = 9; / * menghantar buffer (copy) kepada pekerja * / w.postMessage (buff); / * mengubah data * / arr [0] = 1; / * Mencetak data setelah pekerja telah mengubahnya * / w.onmessage = (e) => console.group ('[main]'); console.log ('Data yang dikemas kini diterima daripada thread pekerja:% i', arr [0]); console.groupEnd ();  

    Dan, ini juga berfungsi! Data dalam penampan adalah sama seperti data di dalam pekerja.

     [pekerja] Data diterima dari benang utama: 1 [utama] Data yang dikemas kini diterima dari benang pekerja: 7 

    Nilai muncul dikemaskini dalam kedua-dua kes; kedua-dua benang utama dan pekerja sedang melihat dan mengubah data yang sama.

    Kata-kata akhir

    Seperti yang telah saya sebutkan tadi, menggunakan memori yang dikongsi dalam JavaScript bukan tanpa kelemahan. Terserah kepada pemaju untuk memastikan bahawa Urutan pelaksanaan berlaku seperti yang diramalkan dan tidak ada dua benang berlumba-lumba untuk mendapatkan data yang sama kerana tiada siapa yang tahu siapa yang akan memenangi piala tersebut.

    Sekiranya anda berminat dalam memori yang dikongsi lebih banyak, perhatikan dokumentasi Atomics objek. The Objek atomik boleh membantu anda dengan beberapa kesukaran, dengan mengurangkan sifat membaca / menulis dari memori yang dikongsi.