Pengantar Memori Bersama dalam JavaScript
Berbagi memori adalah fitur lanjutan dari JavaScript, yang dapat dimanfaatkan oleh utas (yang secara bersamaan menjalankan bagian dari suatu proses). Berbagi memori berarti tidak memiliki masalah untuk meneruskan data yang diperbarui di antara utas dan semua utas dapat mengakses dan memperbarui data yang sama di memori bersama.
Bukankah itu terdengar indah? Hampir saja. Dalam posting ini, kita lihat saja nanti cara menggunakan memori bersama dalam JavaScript dan bagaimana memutuskan apakah ini yang benar-benar ingin Anda lakukan.
Kelebihan & kekurangan dari memori bersama
Kita gunakan pekerja web untuk buat utas dalam JavaScript. API Pekerja Web memungkinkan kami membuat utas pekerja yang dapat digunakan untuk itu jalankan kode di latar belakang sehingga utas utama bebas untuk melanjutkan eksekusi, kemungkinan memproses acara UI, memastikan tidak ada UI yang beku.
Utas pekerja berjalan bersamaan dengan utas utama dan satu sama lain. Eksekusi simultan dari bagian tugas yang berbeda seperti ini menghemat waktu. Anda selesai lebih cepat, tetapi ia juga memiliki masalah sendiri.
Memastikan bahwa setiap utas mendapatkan sumber daya yang diperlukan dan berkomunikasi satu sama lain secara tepat waktu adalah tugas itu sendiri, di mana kecelakaan dapat menghasilkan hasil yang mengejutkan. Atau jika satu utas mengubah data dan yang lainnya membacanya pada waktu bersamaan, menurut Anda apa yang akan dilihat utas lainnya? Pembaruan atau data lama?
Namun, pekerja web tidak mudah dikacaukan. Selama komunikasi mereka melalui penggunaan pesan, data yang mereka kirim adalah satu sama lain bukan yang asli tetapi salinan, artinya tidak Bagikan data yang sama. Mereka lulus salinan data satu sama lain Saat dibutuhkan.
Tetapi berbagi itu peduli, dan banyak utas mungkin juga perlu melihat data yang sama pada saat yang sama dan mengubahnya. Begitu, pelarangan berbagi adalah hal yang tidak boleh. Di sinilah tempat SharedArrayBuffer
objek masuk ke dalam gambar. Itu akan membiarkan kita bagikan data biner di antara banyak utas.
Itu SharedArrayBuffer
obyek
Alih-alih mengirimkan salinan data di antara utas, kami lulus salinan SharedArrayBuffer
obyek. SEBUAH SharedArrayBuffer
obyek menunjuk ke memori tempat data disimpan.
Jadi, bahkan ketika salinan SharedArrayBuffer
dilewatkan di antara utas, mereka semua masih akan menunjuk ke memori yang sama tempat data asli disimpan. Jadi, utas dapat melihat dan memperbarui data dalam memori yang sama.
Pekerja web tanpa Berbagi memori
Untuk melihat bagaimana seorang pekerja web bekerja tanpa menggunakan memori bersama, kami buat utas pekerja dan meneruskan beberapa data ke sana.
Itu index.html
file memegang naskah utama di dalam a tag, seperti yang Anda lihat di bawah:
const w = Pekerja baru ('worker.js'); var n = 9; w.postMessage (n);
Itu pekerja.js
file membawa naskah pekerja:
onmessage = (e) => console.group ('[pekerja]'); console.log ('Data diterima dari utas utama:% i', e.data); console.groupEnd ();
Dengan menggunakan kode di atas, kita mendapatkan yang berikut ini output di konsol:
[pekerja] Data diterima dari utas utama: 9
Anda dapat membaca posting saya yang disebutkan di web pekerja untuk penjelasan kode lengkap dari cuplikan di atas.
Untuk saat ini, perlu diingat bahwa data adalah dikirim bolak-balik di antara utas menggunakan postMessage ()
metode. Datanya adalah diterima di sisi lain oleh pesan
pengendali acara, sebagai nilai acara data
milik.
Sekarang, jika kita ubah data apakah akan muncul diperbarui di ujung penerima? Ayo lihat:
const w = Pekerja baru ('worker.js'); var n = 9; w.postMessage (n); n = 1;
Seperti yang diharapkan, data telah tidak telah diperbarui:
[pekerja] Data diterima dari utas utama: 9
Mengapa itu terjadi? Nya hanya klon yang dikirim ke pekerja dari skrip utama.
Pekerja web dengan Berbagi memori
Sekarang kita akan menggunakan SharedArrayBuffer
obyek dalam contoh yang sama. Kita bisa membuat yang baru SharedArrayBuffer
contoh oleh menggunakan baru
kata kunci. Konstruktor mengambil satu parameter; Sebuah nilai panjang dalam byte, menentukan ukuran buffer.
const w = Pekerja baru ('worker.js'); buff = SharedArrayBuffer (1) baru; var arr = new Int8Array (buff); / * data pengaturan * / arr [0] = 9; / * mengirim buffer (copy) ke pekerja * / w.postMessage (buff);
Perhatikan bahwa a SharedArrayBuffer
obyek hanya mewakili area memori bersama. Untuk melihat dan mengubah data biner, kita perlu menggunakan struktur data yang sesuai (a TypedArray
atau a DataView
obyek).
Dalam index.html
file di atas, baru SharedArrayBuffer
dibuat, dengan panjang hanya satu byte. Lalu, baru Int8Array
, yang merupakan salah satu jenis TypedArray
benda, digunakan untuk atur data ke “9” di ruang byte yang disediakan.
onmessage = (e) => var arr = new Int8Array (e.data); console.group ('[pekerja]'); console.log ('Data diterima dari utas utama:% i', arr [0]); console.groupEnd ();
Int8Array
juga digunakan dalam pekerja, untuk lihat data di buffer.
Itu nilai yang diharapkan muncul di konsol dari utas pekerja, itulah yang kami inginkan:
[pekerja] Data diterima dari utas utama: 9
Sekarang, ayo perbarui data di utas utama untuk melihat apakah perubahan tersebut tercermin pada pekerja.
const w = Pekerja baru ('worker.js'), buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * data pengaturan * / arr [0] = 9; / * mengirim buffer (copy) ke pekerja * / w.postMessage (buff); / * mengubah data * / arr [0] = 1;
Dan, seperti yang Anda lihat di bawah, pembaruan mencerminkan di dalam pekerja!
[pekerja] Data diterima dari utas utama: 1
Tapi, kodenya juga perlu bekerja sebaliknya: ketika nilai pekerja berubah pada awalnya, itu juga perlu diperbarui ketika itu dicetak dari utas utama.
Dalam hal ini, kode kami terlihat seperti ini:
onmessage = (e) => var arr = new Int8Array (e.data); console.group ('[pekerja]'); console.log ('Data diterima dari utas utama:% i', arr [0]); console.groupEnd (); / * mengubah data * / arr [0] = 7; / * posting ke utas utama * / postMessage (");
Itu data diubah pada pekerja dan sebuah pesan kosong diposting ke utas utama menandakan bahwa data dalam buffer telah diubah dan siap untuk utas utama untuk di-output.
const w = Pekerja baru ('worker.js'), buff = new SharedArrayBuffer (1); var arr = new Int8Array (buff); / * data pengaturan * / arr [0] = 9; / * mengirim buffer (copy) ke pekerja * / w.postMessage (buff); / * mengubah data * / arr [0] = 1; / * mencetak data setelah pekerja mengubahnya * / w.onmessage = (e) => console.group ('[main]'); console.log ('Data yang diperbarui diterima dari utas pekerja:% i', arr [0]); console.groupEnd ();
Dan, ini juga berhasil! Data dalam buffer sama dengan data di dalam pekerja.
[pekerja] Data yang diterima dari utas utama: 1 [utama] Data terbaru yang diterima dari utas pekerja: 7
Nilai muncul diperbarui dalam kedua kasus; baik utas utama dan pekerja melihat dan mengubah data yang sama.
Kata-kata terakhir
Seperti yang saya sebutkan sebelumnya, menggunakan memori bersama dalam JavaScript bukan tanpa kerugian. Terserah pengembang untuk memastikan bahwa urutan eksekusi terjadi seperti yang diperkirakan dan tidak ada dua utas berlomba untuk mendapatkan data yang sama karena tidak ada yang tahu siapa yang akan mengambil trofi.
Jika Anda lebih tertarik pada memori bersama, lihat dokumentasi Atom
obyek. Itu Objek atom dapat membantu Anda dengan beberapa kesulitan, dengan mengurangi sifat membaca / menulis yang tidak terduga dari memori bersama.