Apakah Mutex dibutuhkan dalam javascript?

104

Saya telah melihat tautan ini: Menerapkan Pengecualian Bersama dalam JavaScript . Di sisi lain, saya telah membaca bahwa tidak ada utas di javascript, tetapi apa sebenarnya artinya itu?

Ketika peristiwa terjadi, di mana dalam kode tersebut dapat mengganggu?

Dan jika tidak ada utas di JS, apakah saya perlu menggunakan mutex di JS atau tidak?

Secara khusus, saya bertanya-tanya tentang efek dari menggunakan fungsi yang disebut oleh setTimeout()dan XmlHttpRequest's onreadystatechangepada variabel dapat diakses secara global.

Ovesh
sumber
1
Tidak, tidak ada mutex atau alat kontrol konkurensi lainnya di javascript. Lihat Mengapa tidak ada alat kontrol konkurensi di javascript .
Uzair Farooq

Jawaban:

101

Javascript didefinisikan sebagai bahasa reentrant yang berarti tidak ada threading yang diekspos ke pengguna, mungkin ada untaian dalam penerapannya. Fungsi seperti setTimeout()dan callback asinkron harus menunggu mesin skrip tidur sebelum dapat dijalankan.

Artinya segala sesuatu yang terjadi dalam suatu acara harus diselesaikan sebelum acara berikutnya diproses.

Karena itu, Anda mungkin memerlukan mutex jika kode Anda melakukan sesuatu yang mengharapkan nilai tidak berubah antara saat peristiwa asinkron dipicu dan saat callback dipanggil.

Misalnya jika Anda memiliki struktur data di mana Anda mengklik satu tombol dan mengirimkan XmlHttpRequest yang memanggil callback, mengubah struktur data dengan cara yang merusak, dan Anda memiliki tombol lain yang mengubah struktur data yang sama secara langsung, antara saat peristiwa itu terjadi. diaktifkan dan ketika panggilan kembali dijalankan, pengguna dapat mengklik dan memperbarui struktur data sebelum panggilan balik yang kemudian dapat kehilangan nilainya.

Meskipun Anda dapat membuat kondisi balapan seperti itu, sangat mudah untuk mencegahnya dalam kode Anda karena setiap fungsi akan bersifat atomik. Ini akan menjadi pekerjaan yang berat dan mengambil beberapa pola pengkodean yang aneh untuk menciptakan kondisi balapan sebenarnya.

William
sumber
14
Tidak sulit sama sekali untuk membuat kondisi balapan ini: misalnya, saya memiliki acara "onkeyup" di lapangan, yang memicu panggilan ajax ke DB untuk mendapatkan beberapa nilai. Mengetik data dengan cepat dapat dengan mudah menghasilkan hasil yang rusak.
thomasb
19

Jawaban atas pertanyaan ini agak ketinggalan jaman meskipun benar pada saat diberikan. Dan masih benar jika melihat aplikasi javascript sisi klien yang TIDAK menggunakan webworkers.

Artikel tentang web-worker:
multithreading dalam javascript menggunakan webworkers
Mozilla pada webworkers

Ini jelas menunjukkan bahwa javascript melalui pekerja web memiliki kemampuan multithreading. Mengenai pertanyaan apakah mutex diperlukan dalam javascript? Saya tidak yakin akan hal ini. Tetapi posting stackoverflow ini tampaknya relevan:
Pengecualian Saling untuk N Thread Asinkron

gorillatron.dll
sumber
3
ledakan dari masa lalu, tetapi saya menemukan kebutuhan akan mutex ketika banyak tab mengakses penyimpanan lokal yang sama
psp
3
WebWorkers tidak memengaruhi masuk kembali karena mereka tidak berbagi status variabel dan hanya berkomunikasi dengan utas utama dengan meneruskan pesan, yang memicu peristiwa.
Alnitak
9

Seperti yang @william tunjukkan,

Anda mungkin memerlukan mutex jika kode Anda melakukan sesuatu yang diharapkan nilainya tidak berubah antara saat peristiwa asinkron dipicu dan saat callback dipanggil.

Ini dapat digeneralisasikan lebih lanjut - jika kode Anda melakukan sesuatu yang mengharapkan kontrol eksklusif atas sumber daya hingga permintaan asinkron terselesaikan, Anda mungkin memerlukan mutex.

Contoh sederhananya adalah di mana Anda memiliki tombol yang mengaktifkan panggilan ajax untuk membuat rekaman di back end. Anda mungkin memerlukan sedikit kode untuk melindungi Anda dari pemicu pengguna yang senang mengklik pergi dan dengan demikian membuat banyak catatan. Ada sejumlah pendekatan untuk masalah ini (misalnya menonaktifkan tombol, mengaktifkan sukses di ajax). Anda juga bisa menggunakan kunci sederhana:

var save_lock = false;
$('#save_button').click(function(){
    if(!save_lock){
        //lock
        save_lock=true;
        $.ajax({
            success:function()
                //unlock
                save_lock = false;  
            }
        });
    }
}

Saya tidak yakin apakah itu pendekatan terbaik dan saya akan tertarik untuk melihat bagaimana orang lain menangani pengecualian timbal balik dalam javascript, tetapi sejauh yang saya tahu itu mutex sederhana dan berguna.

alzclarke.dll
sumber
4
Saya hampir tidak akan menyebutnya mutex, setidaknya tidak dalam pengertian tradisional, karena Anda tidak memiliki dua utas yang berjalan dalam konteks satu blok kapan saja.
Ovesh
10
mutex hanyalah algoritme yang membantu 'menghindari penggunaan sumber daya umum secara bersamaan'. Meskipun multithreading menciptakan kebutuhan akan mutex, tidak ada dalam definisi yang mengatakan mutex khusus untuk situasi yang Anda gambarkan.
alzclarke
1
Anda benar tentang definisi formal mutex. Tapi ini bukan yang dipikirkan orang ketika mereka berbicara tentang mutex di dunia nyata.
Ovesh
Ini tidak bekerja seperti yang diharapkan. Sayangnya, klik berulang masih akan mengaktifkan panggilan ajax. Ada ide lain?
Mohammed Shareef C
1
Cukup yakin ini harus dibungkus whiledengan setTimeoutatau setIntervaldengan clearIntervalsetelah n kegagalan sehingga Anda memiliki logika coba lagi & batas waktu. Membiarkan apa adanya berarti Anda baru saja melewati kode yang terkunci. Penanganan eksternal dengan mutex dan objek bersama sama pentingnya dengan implementasinya sendiri.
MrMesees
6

JavaScript adalah utas tunggal ... meskipun Chrome mungkin adalah binatang baru (saya pikir itu juga utas tunggal, tetapi setiap tab memiliki utas JavaScript sendiri ... Saya belum memeriksanya secara detail, jadi jangan mengutip saya sana).

Namun, satu hal yang perlu Anda khawatirkan adalah bagaimana JavaScript Anda akan menangani beberapa permintaan ajax yang datang kembali dalam urutan yang tidak sama saat Anda mengirimnya. Jadi, yang benar-benar perlu Anda khawatirkan adalah memastikan panggilan ajax Anda ditangani sedemikian rupa sehingga tidak akan menginjak kaki satu sama lain jika hasilnya muncul dalam urutan yang berbeda dari yang Anda kirimkan.

Ini juga berlaku untuk batas waktu ...

Ketika JavaScript mengembangkan multithreading, maka mungkin khawatir tentang mutex dan sejenisnya ....

Mike Stone
sumber
4

Ya, mutexes dapat diperlukan dalam Javascript ketika mengakses sumber daya yang dibagi antara tab / jendela, seperti localStorage .

Misalnya, jika pengguna membuka dua tab, kode sederhana seperti berikut ini tidak aman:

function appendToList(item) {
    var list = localStorage["myKey"];
    if (list) {
        list += "," + item;
    }
    else {
        list = item;
    }
    localStorage["myKey"] = list;
}

Antara waktu item localStorage adalah 'got' dan 'set', tab lain mungkin telah mengubah nilainya. Ini umumnya tidak mungkin, tetapi mungkin - Anda harus menilai sendiri kemungkinan dan risiko yang terkait dengan perselisihan apa pun dalam keadaan khusus Anda.

Lihat artikel berikut untuk detail lebih lanjut:

memutuskan
sumber
2

JavaScript, bahasanya , bisa multithread sesuai keinginan Anda, tetapi embeddings browser mesin javascript hanya menjalankan satu callback (onload, onfocus, <script>, dll ...) pada satu waktu (per tab, mungkin). Saran William menggunakan Mutex untuk perubahan antara mendaftar dan menerima panggilan balik tidak boleh dianggap terlalu harfiah karena ini, karena Anda tidak ingin memblokir dalam panggilan balik intervensi karena panggilan balik yang akan membukanya akan diblokir di belakang panggilan balik saat ini ! (Wow, bahasa Inggris payah untuk berbicara tentang threading.) Dalam kasus ini, Anda mungkin ingin melakukan sesuatu di sepanjang baris pengiriman ulang acara saat ini jika sebuah bendera disetel, baik secara harfiah atau dengan semacam setTimeout ().

Jika Anda menggunakan penyematan JS yang berbeda, dan itu mengeksekusi beberapa utas sekaligus, itu bisa menjadi sedikit lebih tidak pasti, tetapi karena cara JS dapat menggunakan callback dengan begitu mudah dan mengunci objek pada akses properti, penguncian eksplisit hampir tidak diperlukan . Namun, saya akan terkejut jika embedding yang dirancang untuk kode umum (misalnya, game scripting) yang menggunakan multi threading juga tidak memberikan beberapa primitif penguncian eksplisit.

Maaf untuk dinding teks!

Simon Buchan
sumber
0

Peristiwa diberi isyarat, tetapi eksekusi JavaScript masih bersifat single-threaded.

Pemahaman saya adalah bahwa ketika event ditandai mesin berhenti apa yang sedang dijalankan pada saat menjalankan event handler. Setelah penangan selesai, eksekusi skrip dilanjutkan. Jika event handler mengubah beberapa variabel bersama, kode yang dilanjutkan akan melihat perubahan ini muncul "tiba-tiba".

Jika Anda ingin "melindungi" data bersama, flag boolean sederhana sudah cukup.

Constantin
sumber