Mengapa JavaScript tidak mendukung multithreading?

269

Apakah ini keputusan desain yang disengaja atau masalah dengan browser saat ini kami yang akan diperbaiki dalam versi yang akan datang?

Niyaz
sumber
3
Lihat juga jawaban untuk pertanyaan JavaScript dan Utas untuk informasi tentang utas web / utas pekerja.
Sam Hasler
115
Halo, sesama Googler. Anda mungkin memperhatikan bahwa semua yang ada di sini nampaknya cukup bertanggal (perhatikan pertanyaan ini ditanyakan lebih dari 5 tahun yang lalu.) Sejak ditanyakan, browser web telah memperoleh beberapa kemampuan yang, sejauh yang saya tahu, kurang-lebih multithreading. Lihatlah Pekerja Web: msdn.microsoft.com/en-us/hh549259.aspx
ArtOfWarfare
2
Multithread.js membungkus Pekerja Web dan memungkinkan multithreading mudah di JS. Bekerja di semua browser baru, termasuk iOS Safari. :)
kwh
1
Kemungkinan duplikat dari JavaScript dan Thread
Matt

Jawaban:

194

JavaScript tidak mendukung multi-threading karena penerjemah JavaScript di browser adalah utas tunggal (AFAIK). Bahkan Google Chrome tidak akan membiarkan JavaScript satu halaman web berjalan secara bersamaan karena ini akan menyebabkan masalah konkurensi besar di halaman web yang ada. Semua yang dilakukan Chrome adalah memisahkan beberapa komponen (tab berbeda, plug-in, dan sebagainya) ke dalam proses terpisah, tetapi saya tidak dapat membayangkan satu halaman memiliki lebih dari satu utas JavaScript.

Namun Anda dapat menggunakan, seperti yang disarankan, setTimeoutuntuk memungkinkan semacam penjadwalan dan konkurensi "palsu". Ini menyebabkan browser mendapatkan kembali kendali atas rendering thread, dan memulai kode JavaScript yang diberikan setTimeoutsetelah jumlah milidetik yang diberikan. Ini sangat berguna jika Anda ingin memperbolehkan viewport (apa yang Anda lihat) untuk menyegarkan saat melakukan operasi di atasnya. Hanya dengan mengulang-ulang misalnya koordinat dan memperbarui elemen yang sesuai hanya akan membiarkan Anda melihat posisi awal dan akhir, dan tidak ada di antara keduanya.

Kami menggunakan pustaka abstraksi dalam JavaScript yang memungkinkan kami membuat proses dan utas yang semuanya dikelola oleh penerjemah JavaScript yang sama. Ini memungkinkan kami untuk melakukan tindakan dengan cara berikut:

  • Proses A, Thread 1
  • Proses A, Thread 2
  • Proses B, Thread 1
  • Proses A, Thread 3
  • Proses A, Thread 4
  • Proses B, Thread 2
  • Jeda Proses A
  • Proses B, Thread 3
  • Proses B, Thread 4
  • Proses B, Thread 5
  • Mulai Proses A
  • Proses A, Thread 5

Ini memungkinkan beberapa bentuk penjadwalan dan pemalsuan paralelisme, memulai dan menghentikan utas, dan sebagainya, tetapi itu tidak akan benar multi-threading. Saya tidak berpikir itu akan pernah diimplementasikan dalam bahasa itu sendiri, karena multi-threading benar hanya berguna jika browser dapat menjalankan satu halaman multi-threaded (atau bahkan lebih dari satu inti), dan kesulitan ada cara yang lebih besar dari kemungkinan ekstra.

Untuk masa depan JavaScript, lihat ini: https://developer.mozilla.org/presentations/xtech2006/javascript/

Kamiel Wanrooij
sumber
73
Saya pikir tidak pernah menerapkan visi yang terlalu sempit. Saya menjamin aplikasi web pada akhirnya akan dapat benar-benar multithreaded (hanya logis, karena aplikasi web menjadi lebih dominan, dan perangkat keras menjadi lebih paralel), dan seperti yang saya lihat, karena JavaScript adalah bahasa de-facto dari pengembangan web, itu pada akhirnya harus mendukung multithreading atau digantikan oleh sesuatu yang tidak.
devios1
6
Tidak pernah mungkin sedikit pernyataan yang terlalu berani :) tapi saya masih berpikir keuntungan dari javascript multithreaded benar tidak layak di masa mendatang;)
Kamiel Wanrooij
5
Meskipun saya berpendapat bahwa pekerja web lebih bersamaan melalui model proses daripada model thread. Pekerja web menggunakan pesan lewat sebagai alat komunikasi, yang merupakan solusi elegan untuk masalah konkurensi 'biasa' dalam aplikasi multithreaded. Saya tidak yakin apakah mereka benar-benar dapat beroperasi pada objek yang sama dengan halaman utama secara bersamaan. Sejauh ini saya tidak dapat mengakses DOM. Sebagian besar dari ini adalah semantik, pekerja web terlihat menjanjikan untuk semua maksud dan tujuan.
Kamiel Wanrooij
kesulitan ada cara yang lebih besar dari kemungkinan tambahan Saya tidak yakin jika Anda memikirkan semua kemungkinan tambahan. Saya terutama memikirkan kasus-kasus di mana webgl digunakan seperti dalam permainan atau visualisasi grafis. Misalnya pertimbangkan versi 3D baru Google Maps. Di kota-kota dengan banyak model 3D, PC saya perlu ~ 2 menit untuk memuat semuanya ketika banyak rumah harus dirender. Pada sudut tertentu, baik kartu grafis saya maupun jaringan saya tidak bekerja sesuai kapasitas. Tetapi 1 dari 8 prosesor berada pada 100%. Multithreading juga merupakan masalah besar dalam hal fps seperti yang ditunjukkan contoh ini: youtube.com/watch?v=sJ2p982cZFc
Scindix
25

JavaScript multi-threading (dengan beberapa batasan) ada di sini. Pekerja yang diterapkan Google untuk Gears, dan pekerja disertakan dengan HTML5. Sebagian besar browser telah menambahkan dukungan untuk fitur ini.

Keamanan data dijamin karena semua data yang dikomunikasikan ke / dari pekerja diserialisasi / disalin.

Untuk info lebih lanjut, baca:

http://www.whatwg.org/specs/web-workers/current-work/

http://ejohn.org/blog/web-workers/

Neil
sumber
8
Tapi bukankah lebih dari pendekatan multi-proses daripada multi-threaded? Utas diketahui bekerja dalam satu tumpukan.
daging sapi
1
@ beefather, itu benar. Ini lebih merupakan pendekatan proses.
Neil
23

Secara tradisional, JS dimaksudkan untuk potongan kode yang pendek dan berjalan cepat. Jika Anda memiliki perhitungan besar terjadi, Anda melakukannya di server - ide dari JS + HTML aplikasi yang berlari di browser Anda untuk jangka waktu yang lama melakukan hal-hal non-sepele itu tidak masuk akal.

Tentu saja, sekarang kita memilikinya. Tetapi, browser akan perlu sedikit untuk mengejar ketinggalan - kebanyakan dari mereka telah dirancang di sekitar model single-threaded, dan mengubah itu tidak mudah. Google Gears menyampingkan banyak masalah potensial dengan mengharuskan eksekusi latar belakang diisolasi - tidak mengubah DOM (karena itu bukan utas-aman), tidak ada objek mengakses yang dibuat oleh utas utama (ditto). Meskipun membatasi, ini kemungkinan akan menjadi desain paling praktis untuk waktu dekat, baik karena menyederhanakan desain browser, dan karena itu mengurangi risiko yang terlibat dalam memungkinkan JS coders yang tidak berpengalaman mengacau dengan utas ...

@marcio :

Mengapa itu alasan untuk tidak mengimplementasikan multi-threading di Javascript? Pemrogram dapat melakukan apa pun yang mereka inginkan dengan alat yang mereka miliki.

Jadi, jangan beri mereka alat yang sangat mudah disalahgunakan sehingga setiap situs web lain yang saya buka akhirnya mogok di peramban saya. Implementasi naif dari ini akan membawa Anda langsung ke wilayah yang menyebabkan MS sakit kepala begitu banyak selama pengembangan IE7: add-on penulis bermain cepat dan longgar dengan model threading, menghasilkan bug tersembunyi yang menjadi jelas ketika siklus hidup objek berubah pada utas primer . BURUK. Jika Anda menulis add-on ActiveX multi-threaded untuk IE, saya kira itu datang dengan wilayah tersebut; tidak berarti perlu melangkah lebih jauh dari itu.

Shog9
sumber
6
"itu mengurangi risiko yang terlibat> dalam mengizinkan JS coders yang tidak berpengalaman> bermain-main dengan utas" Mengapa itu alasan untuk tidak mengimplementasikan multi-threading di Javascript? Pemrogram dapat melakukan apa pun yang mereka inginkan dengan alat yang mereka miliki. Jika itu baik atau buruk, itu masalah mereka. Dengan model proses Google Chrome bahkan tidak dapat mempengaruhi aplikasi lain. :)
Marcio Aguiar
3
@ Shog9 - "Jangan berikan alat [programmer] yang sangat mudah disalahgunakan sehingga setiap situs web lain yang saya buka akhirnya mogok di peramban saya." - Apa? Dengan logika yang sama, tidak ada bahasa yang harus memiliki multithreading, karena jika mereka menawarkan bahwa setiap program lain yang Anda coba buka akan crash. Kecuali itu tidak bekerja seperti itu. Threading ada di sebagian besar bahasa dan kebanyakan programmer pemula tidak menyentuhnya, dan sebagian besar yang tidak memproduksinya, dan aplikasi yang tidak pernah menjadi populer atau digunakan secara luas.
ArtOfWarfare
11

Saya tidak tahu alasan untuk keputusan ini, tetapi saya tahu Anda dapat mensimulasikan beberapa manfaat pemrograman multi-utas menggunakan setTimeout. Anda dapat memberikan ilusi banyak proses melakukan hal-hal pada saat yang sama, meskipun dalam kenyataannya, semuanya terjadi dalam satu utas.

Biarkan saja fungsi Anda melakukan sedikit pekerjaan, dan kemudian panggil sesuatu seperti:

setTimeout(function () {
    ... do the rest of the work...
}, 0);

Dan segala hal lain yang perlu dilakukan (seperti pembaruan UI, gambar animasi, dll) akan terjadi ketika mereka mendapat kesempatan.

pkaeding
sumber
Sebagian besar kasus saya ingin menggunakan bagian loopdalam setTimeouttetapi ternyata itu tidak berhasil. Pernahkah Anda melakukan hal seperti itu atau Anda memiliki retasan? contoh akan untuk array 1000 elemen, saya berharap untuk menggunakan dua untuk loop di dalam dua setTimeoutpanggilan sedemikian rupa sehingga loop pertama melalui dan mencetak elemen 0..499, loop kedua melalui dan elemen cetak 500..999.
benjaminz
Biasanya tekniknya adalah menyelamatkan negara dan melanjutkan. Misalnya, Anda ingin mencetak 0 hingga 1000, Anda dapat mencetak 0 hingga 499 dan kemudian melakukan trik setTimeout dengan argumen 500. Kode di dalamnya akan tahu untuk mengambil argumen (500) dan memulai perulangan dari sana.
Eyal
8

Maksud Anda mengapa bahasa tidak mendukung multithreading atau mengapa mesin JavaScript di browser tidak mendukung multithreading?

Jawaban untuk pertanyaan pertama adalah bahwa JavaScript di browser dimaksudkan untuk dijalankan di kotak pasir dan dengan cara mesin / OS-independen, untuk menambahkan dukungan multithreading akan mempersulit bahasa dan mengikat bahasa terlalu dekat ke OS.

matt b
sumber
6

Node.js 10.5+ mendukung utas pekerja sebagai fitur eksperimental (Anda dapat menggunakannya dengan bendera pekerja-ekperimental diaktifkan): https://nodejs.org/api/worker_threads.html

Jadi, aturannya adalah:

  • jika Anda perlu melakukan operasi terikat I / O , maka gunakan mekanisme internal (alias callback / janji / async-tunggu)
  • jika Anda perlu melakukan operasi terikat CPU , maka gunakan utas pekerja.

Utas pekerja dimaksudkan sebagai utas yang tahan lama, artinya Anda menelurkan utas latar dan kemudian Anda berkomunikasi dengannya melalui passing pesan.

Jika tidak, jika Anda perlu mengeksekusi beban CPU yang berat dengan fungsi anonim, maka Anda dapat menggunakan https://github.com/wilk/microjob , perpustakaan kecil yang dibangun di sekitar utas pekerja.

Sial
sumber
4

Seperti kata matt b, pertanyaannya tidak terlalu jelas. Dengan asumsi bahwa Anda bertanya tentang dukungan multithreading dalam bahasa: karena itu tidak diperlukan untuk 99,999% dari aplikasi yang berjalan di browser saat ini. Jika Anda benar-benar membutuhkannya, ada solusi (seperti menggunakan window.setTimeout).

Secara umum multithreading sangat, sangat, sangat, sangat, sangat, sangat sulit (apakah saya mengatakan bahwa itu sulit?) Untuk mendapatkan yang benar, kecuali Anda memasukkan batasan tambahan (seperti hanya menggunakan data yang tidak dapat diubah).

Grey Panther
sumber
3

Intel telah melakukan beberapa penelitian open-source tentang multithreading di Javascript, baru-baru ini dipamerkan di GDC 2012. Ini adalah tautan untuk videonya . Kelompok penelitian menggunakan OpenCL yang terutama berfokus pada Intel Chip set dan OS Windows. Proyek ini diberi nama kode RiverTrail dan kodenya tersedia di GitHub

Beberapa tautan yang lebih bermanfaat:

Membangun Jalan Raya Komputasi untuk Aplikasi Web

Rohit Reddy Korrapolu
sumber
1

Implementasi yang tidak mendukung multi-threading. Saat ini Google Gears menyediakan cara untuk menggunakan beberapa bentuk konkurensi dengan menjalankan proses eksternal, tetapi hanya itu.

Peramban baru yang seharusnya dirilis Google hari ini (Google Chrome) menjalankan beberapa kode secara paralel dengan memisahkannya dalam proses.

Bahasa inti, tentu saja dapat memiliki dukungan yang sama seperti, katakanlah Java, tetapi dukungan untuk sesuatu seperti konkurensi Erlang tidak ada di dekat cakrawala.

Greg Roberts
sumber
1

Javascript adalah bahasa utas tunggal. Ini berarti ia memiliki satu tumpukan panggilan dan satu tumpukan memori. Seperti yang diharapkan, ia mengeksekusi kode dalam urutan dan harus menyelesaikan mengeksekusi kode bagian sebelum pindah ke yang berikutnya. Ini sinkron, tetapi kadang-kadang bisa berbahaya. Sebagai contoh, jika suatu fungsi membutuhkan waktu untuk mengeksekusi atau harus menunggu sesuatu, sementara itu membekukan semuanya.

Omar bakhsh
sumber
0

Sejauh yang saya dengar Google Chrome akan memiliki javascript multithreaded, jadi ini adalah masalah "implementasi saat ini".

BlaM
sumber
0

Tanpa dukungan bahasa yang tepat untuk sinkronisasi ulir, bahkan tidak masuk akal untuk mencoba implementasi baru. Aplikasi JS kompleks yang ada (mis. Apa pun yang menggunakan ExtJS) kemungkinan besar akan mogok secara tak terduga, tetapi tanpa synchronizedkata kunci atau yang serupa, juga akan sangat sulit atau bahkan tidak mungkin untuk menulis program baru yang berperilaku dengan benar.

Erich Kitzmueller
sumber
-1

Namun Anda dapat menggunakan fungsi eval untuk membawa konkurensi ke BEBERAPA EXTENT

/* content of the threads to be run */
var threads = [
        [
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');"
        ],
        [
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');"
        ]
    ];

window.onload = function() {
    var lines = 0, quantum = 3, max = 0;

    /* get the longer thread length */
    for(var i=0; i<threads.length; i++) {
        if(max < threads[i].length) {
            max = threads[i].length;
        }
    }

    /* execute them */
    while(lines < max) {
        for(var i=0; i<threads.length; i++) {
            for(var j = lines; j < threads[i].length && j < (lines + quantum); j++) {
                eval(threads[i][j]);
            }
        }
        lines += quantum;
    }
}
Madhusoodan P
sumber
-2

Multi-threading dengan javascript jelas dimungkinkan menggunakan webworkers yang dibawa oleh HTML5.

Perbedaan utama antara pekerja web dan lingkungan multi-threading standar adalah sumber daya memori tidak dibagi dengan utas utama, referensi ke objek tidak terlihat dari satu utas ke utas lainnya. Utas berkomunikasi dengan bertukar pesan, oleh karena itu dimungkinkan untuk menerapkan sinkronisasi dan algoritma metode panggilan bersamaan mengikuti pola desain yang digerakkan oleh peristiwa.

Ada banyak kerangka kerja yang memungkinkan untuk menyusun program di antara utas, di antaranya OODK-JS, kerangka kerja OOP yang mendukung pemrograman bersamaan https://github.com/GOMServices/oodk-js-oop-for-js

OBDM
sumber
5
Berbagi memori adalah definisi yang tepat dari Thread yang berlawanan dengan proses yang terpisah (mis. Fork () vs exec ()). Thread dapat berbagi objek, proses harus menggunakan IPC. Pekerja Web tidak multithreading.
felixfbecker