Apa yang dapat dilakukan beberapa utas yang tidak dapat dilakukan oleh satu utas? [Tutup]

100

Sementara utas dapat mempercepat eksekusi kode, apakah sebenarnya dibutuhkan? Bisakah setiap bagian kode dilakukan dengan menggunakan utas tunggal atau adakah sesuatu yang ada yang hanya dapat dicapai dengan menggunakan beberapa utas?

AngryBird
sumber
29
Berdasarkan beberapa jawaban yang sudah diposting di sini, saya pikir ada beberapa klarifikasi. Tujuan dari threading adalah untuk memungkinkan komputer (tampak) melakukan lebih dari satu hal sekaligus. Jika ini dilakukan dengan menggunakan komputer dengan satu inti, Anda tidak akan melihat peningkatan secara keseluruhan. Yang akan Anda lihat adalah membuka blokir; dalam program single-threaded, antarmuka pengguna akan diblokir saat perhitungan sedang berlangsung. Dalam program multi-utas, antarmuka pengguna mungkin masih dapat digunakan saat perhitungan berlangsung di latar belakang.
Robert Harvey
11
Tentu saja, jika Anda memiliki beberapa inti prosesor di komputer Anda (yang sudah biasa saat ini), program Anda dapat menggunakan utas untuk memanfaatkan inti tambahan untuk melakukan pemrosesan Anda, dan Anda akan melihat percepatan, karena Anda melempar lebih banyak daya kuda ke masalah komputasi Anda. Jika Anda tidak menggunakan utas sama sekali, program Anda hanya akan menggunakan inti prosesor tunggal, yang baik-baik saja jika hanya itu yang Anda butuhkan.
Robert Harvey
14
Program single-threaded tidak dapat menemui jalan buntu sumber daya seperti halnya program multi-threaded.
zzzzBov
3
Jawaban: dijalankan dengan dua core
Daniel Little
6
Jawaban: menyebabkan jalan buntu.
Pekerjaan

Jawaban:

111

Pertama-tama, utas tidak dapat mempercepat eksekusi kode. Mereka tidak membuat komputer berjalan lebih cepat. Yang bisa mereka lakukan adalah meningkatkan efisiensi komputer dengan menggunakan waktu yang seharusnya terbuang sia-sia. Dalam beberapa jenis pemrosesan optimasi ini dapat meningkatkan efisiensi dan mengurangi waktu berjalan.

Jawaban sederhananya adalah ya. Anda dapat menulis kode apa saja untuk dijalankan pada satu utas. Bukti: Sistem prosesor tunggal hanya dapat menjalankan instruksi secara linear. Memiliki beberapa jalur eksekusi dilakukan oleh interupsi pemrosesan sistem operasi, menyimpan status utas saat ini, dan memulai yang lain.

The kompleks jawabannya ... lebih kompleks! Alasan mengapa program multithreaded mungkin lebih efisien daripada yang linear adalah karena "masalah" perangkat keras. CPU dapat menjalankan perhitungan lebih cepat daripada memori dan IO penyimpanan keras. Jadi, instruksi "add", misalnya, mengeksekusi jauh lebih cepat daripada "fetch". Tembolok dan instruksi program khusus yang diambil (tidak yakin dengan istilah yang tepat di sini) dapat mengatasi hal ini sampai batas tertentu, tetapi masalah kecepatan tetap ada.

Threading adalah cara memerangi ketidakcocokan ini dengan menggunakan CPU untuk instruksi yang mengikat CPU sementara instruksi IO sedang diselesaikan. Rencana eksekusi utas yang tipikal mungkin adalah: Mengambil data, memproses data, menulis data. Asumsikan bahwa mengambil dan menulis membutuhkan 3 siklus dan pemrosesan memerlukan satu, untuk tujuan ilustrasi. Anda dapat melihat bahwa ketika komputer membaca atau menulis, itu tidak melakukan apa - apa untuk 2 siklus masing-masing? Jelas itu malas, dan kita perlu memecahkan cambuk optimasi kami!

Kita dapat menulis ulang proses menggunakan threading untuk menggunakan waktu yang terbuang ini:

  1. Ambil nomor 1
  2. tidak ada operasi
  3. Ambil nomor 2
  4. # 1 selesai, proses itu
  5. tulis # 1
  6. Ambil nomor 1
  7. # 2 selesai, proses itu
  8. tulis # 2
  9. ambil # 2

Dan seterusnya. Jelas ini adalah contoh yang agak dibuat-buat, tetapi Anda dapat melihat bagaimana teknik ini dapat memanfaatkan waktu yang seharusnya dihabiskan menunggu IO.

Perhatikan bahwa threading seperti yang ditunjukkan di atas hanya dapat meningkatkan efisiensi pada proses terikat IO berat. Jika suatu program terutama menghitung hal-hal, tidak akan ada banyak "lubang" yang bisa kita lakukan lebih banyak lagi. Juga, ada beberapa instruksi tambahan saat beralih di antara utas. Jika Anda menjalankan terlalu banyak utas, CPU akan menghabiskan sebagian besar waktunya untuk beralih dan tidak banyak yang benar-benar mengatasi masalah. Ini disebut meronta - ronta .

Itu semua baik dan bagus untuk prosesor inti tunggal, tetapi kebanyakan prosesor modern memiliki dua atau lebih inti. Utas masih memiliki tujuan yang sama - untuk memaksimalkan penggunaan CPU, tetapi kali ini kami memiliki kemampuan untuk menjalankan dua instruksi terpisah secara bersamaan. Ini dapat mengurangi waktu berjalan dengan faktor berapa banyak core yang tersedia, karena komputer sebenarnya multitasking, bukan konteks switching.

Dengan beberapa inti, utas menyediakan metode kerja pemisahan antara dua inti. Hal di atas masih berlaku untuk setiap inti individu; Sebuah program yang menjalankan efisiensi maksimal dengan dua utas pada satu inti kemungkinan besar akan berjalan pada efisiensi puncak dengan sekitar empat utas pada dua inti. (Efisiensi diukur di sini dengan eksekusi instruksi NOP minimum.)

Masalah dengan menjalankan utas pada beberapa inti (bukan inti tunggal) umumnya diatasi dengan perangkat keras. CPU akan memastikan bahwa ia mengunci lokasi memori yang sesuai sebelum membaca / menulis. (Saya telah membaca bahwa ia menggunakan bit bendera khusus dalam memori untuk ini, tetapi ini dapat dicapai dalam beberapa cara.) Sebagai seorang programmer dengan bahasa tingkat yang lebih tinggi, Anda tidak perlu khawatir tentang apa pun lebih pada dua inti saat Anda harus dengan satu.

TL; DR: Utas dapat dibagi berfungsi agar komputer dapat memproses beberapa tugas secara tidak sinkron. Ini memungkinkan komputer berjalan pada efisiensi maksimum dengan memanfaatkan semua waktu pemrosesan yang tersedia, alih-alih mengunci ketika suatu proses menunggu sumber daya.

Michael K
sumber
17
Jawaban yang sangat bagus. Saya hanya ingin menjelaskan bahwa setelah titik tertentu, menambahkan lebih banyak utas sebenarnya dapat membuat program berjalan lebih lambat , karena semua waktu yang sebelumnya "terbuang" digunakan, dan Anda sekarang hanya menambahkan sakelar konteks tambahan dan overhead sinkronisasi.
Karl Bielefeldt
8
+1 untuk menjelaskan bagaimana utas membantu pemrosesan blokir IO. Penggunaan utas lainnya adalah untuk memungkinkan UI melanjutkan proses tindakan pengguna (gerakan mouse, bilah kemajuan, penekanan tombol) sehingga persepsi pengguna adalah bahwa program belum 'dibekukan'.
jqa
3
Satu lagi tambahan: secara tegas, utas tidak menambahkan ekspresifitas apa pun pada sebagian besar bahasa; Anda bisa, jika Anda benar-benar harus, mengimplementasikan semua multiplexing sendiri dan mendapatkan hasil yang sama. Namun, dalam praktiknya, ini akan berarti menerapkan kembali seluruh pustaka threading Anda - seperti rekursi tidak sepenuhnya diperlukan, tetapi dapat ditiru dengan menulis tumpukan panggilan Anda sendiri.
Kilian Foth
9
@james: Saya akan mengklasifikasikan pemrosesan UI hanya sebagai bentuk I / O. Mungkin yang terburuk, karena pengguna cenderung lamban dan tidak linier. :)
TMN
7
Ada asumsi diam dalam tanya jawab di sekitar komputer menjadi single core atau CPU. Arloji saya memiliki dua inti, saya ragu anggapan ini berlaku untuk semua mesin modern.
blueberryfields
37

Apa yang dapat dilakukan beberapa utas yang tidak dapat dilakukan oleh satu utas?

Tidak ada.

Sketsa bukti sederhana:

  • [Dugaan Gereja-Turing] ⇒ Segala sesuatu yang dapat dihitung dapat dihitung oleh Mesin Universal Turing.
  • Mesin Universal Turing adalah single-threaded.
  • Ergo, semua yang dapat dihitung dapat dihitung dengan satu utas.

Namun, perlu diketahui bahwa ada asumsi besar yang tersembunyi di sana: yaitu bahwa bahasa yang digunakan dalam satu utas adalah Turing-complete.

Jadi, pertanyaan yang lebih menarik adalah: "Bisakah menambahkan hanya multi-threading ke bahasa non-Turing membuatnya menjadi Turing-complete?" Dan saya percaya, jawabannya adalah "Ya".

Mari kita ambil Bahasa Fungsional Total. [Bagi mereka yang tidak terbiasa: sama seperti Pemrograman Fungsional adalah Pemrograman dengan Fungsi, Pemrograman Fungsional Total adalah Pemrograman dengan Fungsi Total.]

Total Fungsional Bahasa jelas bukan Turing-lengkap: Anda tidak dapat menulis loop tak terbatas dalam TFPL (pada kenyataannya, itu cukup banyak definisi "total"), tetapi Anda dapat dalam Mesin Turing, karena ada setidaknya satu program yang tidak dapat ditulis dalam TFPL tetapi bisa dalam UTM, oleh karena itu TFPL kurang kuat secara komputasi daripada UTM.

Namun, segera setelah Anda menambahkan threading ke TFPL, Anda mendapatkan loop tak terbatas: cukup lakukan setiap iterasi dari loop di utas baru. Setiap utas individu selalu mengembalikan hasil, oleh karena itu Total, tetapi setiap utas juga menumbuhkan utas baru yang mengeksekusi iterasi berikutnya , ad infinitum.

Saya pikir bahasa ini akan menjadi Turing-lengkap.

Paling tidak, ini menjawab pertanyaan awal:

Apa yang dapat dilakukan beberapa utas yang tidak dapat dilakukan oleh satu utas?

Jika Anda memiliki bahasa yang tidak dapat melakukan loop tak terbatas, maka multi-threading memungkinkan Anda untuk melakukan loop tak terbatas.

Perhatikan, tentu saja, bahwa menelurkan utas adalah efek samping dan dengan demikian bahasa kita yang luas tidak hanya tidak lagi Total, bahkan bukan Fungsional lagi.

Jörg W Mittag
sumber
13
Karena kamu membawa "bukti", aku tidak bisa mencegah diriku dari "well, sebenarnya ..." ing kamu. Saya pikir Anda menyalahgunakan gagasan komputabilitas. Buktinya adalah hal yang lucu dan saya mengerti maksud Anda, tetapi itu tidak benar-benar pada tingkat abstraksi yang tepat. Tidak dapat melakukan hal-hal tidak sama dengan tidak dapat menghitung , misalnya, Anda tidak dapat menggunakan bukti Anda untuk mengatakan, karena mesin Turing dapat menghitung "setiap fungsi yang dapat dihitung", ia dapat melakukannya dalam 3 detik. Sebenarnya, mesin berulir tunggal tanpa gangguan tidak dapat mengakses I / O sambil menjaga prosesornya sibuk melakukan komputasi.
xmm0
1
Dan, tidak ada komputer nyata adalah mesin Turing.
Jens
1
@ColeJohnson: Kebuntuan adalah detail implementasi. Output yang terlihat "tidak terhenti", yang mudah dilakukan dengan satu utas.
Heinzi
1
@Heinzi: "mudah dilakukan" adalah pernyataan yang meremehkan. Jika saya ingat benar, program kedua atau ketiga yang saya pernah menulis melakukan hal itu! ;-)
Joachim Sauer
1
Jika alam semesta adalah satu utas , maka apa itu teori string ? Anda tidak dapat berdebat dengan sains seperti ini.
corsiKa
22

Secara teori, semua program multithreaded dapat dilakukan dengan program single-threaded juga, lebih lambat.

Dalam praktiknya, perbedaan kecepatan mungkin sangat besar sehingga tidak mungkin seseorang dapat menggunakan program single-threaded untuk tugas tersebut. Misalnya jika Anda memiliki pekerjaan pemrosesan data batch yang berjalan setiap malam, dan dibutuhkan lebih dari 24 jam untuk menyelesaikannya pada satu utas, Anda tidak memiliki pilihan lain selain membuatnya multithreaded. (Dalam praktiknya, ambangnya mungkin bahkan lebih sedikit: sering kali tugas pembaruan tersebut harus selesai pada pagi hari, sebelum pengguna mulai menggunakan sistem lagi. Juga, tugas lain mungkin bergantung pada mereka, yang juga harus selesai pada malam yang sama. runtime yang tersedia mungkin serendah beberapa jam / menit.)

Melakukan pekerjaan komputasi pada banyak utas adalah bentuk pemrosesan terdistribusi; Anda mendistribusikan karya melalui beberapa utas. Contoh lain dari pemrosesan terdistribusi (menggunakan banyak komputer dan bukan beberapa utas) adalah screensaver SETI: menghitung bahwa banyak data pengukuran pada satu prosesor akan memakan waktu yang sangat lama dan para peneliti lebih suka melihat hasilnya sebelum pensiun ;-) Namun, mereka tidak memiliki anggaran untuk menyewa superkomputer begitu lama, sehingga mereka mendistribusikan pekerjaan lebih dari jutaan PC rumah tangga, untuk membuatnya murah.

Péter Török
sumber
Screensaver SETI adalah contoh threading dalam arti berjalan pada utas latar belakang di komputer Anda; Anda masih dapat melakukan hal-hal lain di komputer Anda saat sedang mengolah data di latar belakang. Tanpa utas, akan ada jeda sementara screensaver SETI melakukan perhitungannya; Anda harus menunggu sampai selesai sebelum Anda dapat melanjutkan pekerjaan Anda sendiri.
Robert Harvey
3
@ Robert: Saya pikir Péter menggunakan SETI @ Home untuk menjelaskan konsep pemisahan pekerjaan untuk dijalankan pada banyak prosesor. Komputasi terdistribusi tentu saja berbeda dari multithreading, tetapi konsepnya serupa.
Steven
5
Saya pikir contoh SETI adalah komputasi terdistribusi daripada mutli-threaded. Konsep serupa tetapi tidak sama.
11

Meskipun utas tampaknya merupakan langkah kecil dari perhitungan berurutan, pada kenyataannya, ini merupakan langkah besar. Mereka membuang sifat paling penting dan menarik dari perhitungan berurutan: dapat dimengerti, dapat diprediksi, dan determinisme. Threads, sebagai model perhitungan, sangat tidak deterministik, dan tugas programmer menjadi salah satu pemangkasan yang tidak determinisme.

- Masalah dengan Thread (www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf).

Meskipun ada beberapa keuntungan kinerja yang bisa didapat dengan menggunakan utas di mana Anda dapat mendistribusikan pekerjaan di beberapa inti, mereka sering datang dengan harga yang mahal.

Salah satu kelemahan menggunakan utas yang belum disebutkan di sini adalah hilangnya kompartementalisasi sumber daya yang Anda dapatkan dengan ruang proses berulir tunggal. Misalnya, Anda mengalami kasus segfault. Dalam beberapa kasus, dimungkinkan untuk pulih dari ini dalam aplikasi multi-proses di mana Anda membiarkan anak yang salah mati dan respawn yang baru. Ini adalah kasus di backend prefork Apache. Ketika satu contoh httpd naik ke perut, kasus terburuknya adalah bahwa permintaan HTTP tertentu dapat dibatalkan untuk proses itu tetapi Apache menelurkan anak baru dan sering kali permintaan jika hanya membenci dan dilayani. Hasil akhirnya adalah bahwa Apache secara keseluruhan tidak diturunkan dengan utas yang salah.

Pertimbangan lain dalam skenario ini adalah kebocoran memori. Ada beberapa kasus di mana Anda dapat menangani thread dengan anggun (pada UNIX, memulihkan dari beberapa sinyal tertentu - bahkan segfault / fpviolation) adalah mungkin), tetapi bahkan dalam kasus itu, Anda mungkin telah membocorkan semua memori yang dialokasikan oleh utas itu. (malloc, baru, dll.). Jadi sementara Anda memprosesnya dapat hidup terus, ia membocorkan semakin banyak memori seiring waktu dengan setiap kesalahan / pemulihan. Sekali lagi, ada beberapa cara untuk meminimalkan hal ini seperti penggunaan kumpulan memori Apache. Tapi ini masih tidak melindungi dari memori yang mungkin telah dialokasikan oleh lib pihak ketiga yang mungkin telah digunakan utas.

Dan, seperti yang ditunjukkan beberapa orang, memahami primitif sinkronisasi mungkin merupakan hal yang paling sulit untuk dilakukan dengan benar. Masalah ini dengan sendirinya - hanya mendapatkan logika umum yang tepat untuk semua kode Anda - bisa sangat memusingkan. Kebuntuan misterius cenderung terjadi pada waktu yang paling aneh, dan kadang-kadang bahkan tidak sampai program Anda berjalan dalam produksi, yang membuat proses debug semakin sulit. Tambahkan ke fakta ini bahwa primitif sinkronisasi sering sangat bervariasi dengan platform (Windows vs. POSIX), dan debugging seringkali lebih sulit, serta kemungkinan kondisi balapan kapan saja (startup / inisialisasi, runtime, dan shutdown), pemrograman dengan utas benar-benar memiliki sedikit belas kasihan untuk pemula. Dan bahkan untuk para ahli, masih ada sedikit belas kasihan hanya karena pengetahuan tentang threading itu sendiri tidak meminimalkan kompleksitas secara umum. Setiap baris kode ulir kadang-kadang tampaknya secara eksponensial menambah kompleksitas keseluruhan program dan juga meningkatkan kemungkinan kebuntuan tersembunyi atau kondisi ras aneh muncul kapan saja. Mungkin juga sangat sulit untuk menulis kasus uji untuk menemukan hal-hal ini.

Inilah sebabnya mengapa beberapa proyek seperti Apache dan PostgreSQL sebagian besar berbasis proses. PostgreSQL menjalankan setiap utas backend dalam proses terpisah. Tentu saja ini masih tidak mengurangi masalah sinkronisasi dan kondisi balapan, tetapi hal itu menambah sedikit perlindungan dan dalam beberapa hal menyederhanakan banyak hal.

Beberapa proses yang menjalankan satu utas eksekusi dapat jauh lebih baik daripada beberapa utas yang berjalan dalam satu proses tunggal. Dan dengan munculnya banyak kode peer-to-peer baru seperti AMQP (RabbitMQ, Qpid, dll.) Dan ZeroMQ, jauh lebih mudah untuk memisahkan thread di ruang proses yang berbeda dan bahkan mesin dan jaringan, sangat menyederhanakan hal-hal. Tapi tetap saja, itu bukan peluru perak. Masih ada kerumitan untuk dihadapi. Anda hanya memindahkan beberapa variabel Anda dari ruang proses ke jaringan.

Intinya adalah bahwa keputusan untuk masuk ke domain utas bukanlah keputusan yang ringan. Begitu Anda melangkah ke wilayah itu, hampir seketika semuanya menjadi lebih kompleks dan seluruh jenis masalah baru memasuki hidup Anda. Itu bisa menyenangkan dan keren, tapi itu seperti tenaga nuklir - ketika ada masalah, mereka bisa rusak dan cepat. Saya ingat mengambil kelas dalam pelatihan kritikalitas bertahun-tahun yang lalu dan mereka menunjukkan gambar beberapa ilmuwan di Los Alamos yang bermain dengan plutonium di laboratorium pada Perang Dunia II. Banyak yang mengambil sedikit atau tidak ada tindakan pencegahan terhadap peristiwa pemaparan, dan dalam sekejap mata - dalam satu flash yang terang dan tanpa rasa sakit, semuanya akan berakhir bagi mereka. Beberapa hari kemudian mereka mati. Richard Feynman kemudian menyebutnya sebagai " menggelitik ekor naga"Seperti itulah rasanya bermain dengan utas (setidaknya bagi saya toh). Kelihatannya agak tidak berbahaya pada awalnya, dan pada saat Anda digigit, Anda menggaruk-garuk kepala pada seberapa cepat hal-hal menjadi buruk. Tetapi setidaknya utas menang akan membunuhmu.

Mike Owens
sumber
TL; DR jawab saya artinya jika dibandingkan dengan bagian yang bagus ini tentang apa yang tidak akan dilakukan thread tunggal untuk Anda.
bmike
1
coffee break sore
Mike Owens
10

Pertama, aplikasi berulir tunggal tidak akan pernah memanfaatkan CPU multi-core atau hyper-threading. Tetapi bahkan pada satu inti, CPU ulir tunggal melakukan multi-threading memiliki keunggulan.

Pertimbangkan alternatifnya dan apakah itu membuat Anda bahagia. Misalkan Anda memiliki banyak tugas yang harus dijalankan secara bersamaan. Misalnya Anda harus tetap berkomunikasi dengan dua sistem yang berbeda. Bagaimana Anda melakukan ini tanpa multi-threading? Anda mungkin akan membuat penjadwal Anda sendiri dan membiarkannya memanggil tugas-tugas berbeda yang perlu dilakukan. Ini berarti bahwa Anda perlu membagi tugas Anda menjadi beberapa bagian. Anda mungkin perlu memenuhi beberapa kendala waktu nyata, Anda harus memastikan bahwa komponen Anda tidak memakan terlalu banyak waktu. Kalau tidak, penghitung waktu akan kedaluwarsa dalam tugas lain. Ini membuat pemisahan tugas menjadi lebih sulit. Semakin banyak tugas yang Anda butuhkan untuk mengelola diri sendiri, semakin banyak pemisahan yang perlu Anda lakukan dan semakin rumit penjadwal Anda untuk memenuhi semua kendala.

Ketika Anda memiliki banyak utas, kehidupan bisa menjadi lebih mudah. Penjadwal pre-emptive dapat menghentikan utas kapan saja, mempertahankan statusnya, dan memulai kembali yang lain. Ini akan memulai kembali ketika utas Anda mendapat gilirannya. Keuntungan: kompleksitas penulisan penjadwal telah dilakukan untuk Anda dan Anda tidak harus membagi tugas Anda. Selain itu, penjadwal mampu mengelola proses / utas yang bahkan Anda sendiri tidak sadari. Dan juga, ketika utas tidak perlu melakukan apa-apa (menunggu beberapa peristiwa) itu tidak akan mengambil siklus CPU. Ini tidak mudah dilakukan ketika Anda membuat penjadwal single-threaded down Anda. (Menidurkan sesuatu tidak begitu sulit, tetapi bagaimana ia bangun?)

Kelemahan dari pengembangan multi-utas adalah Anda perlu memahami tentang masalah konkurensi, strategi penguncian, dan sebagainya. Mengembangkan kode multi-utas bebas kesalahan bisa sangat sulit. Dan debugging bisa lebih sulit.

Menandai
sumber
9

apakah ada sesuatu yang ada yang hanya dapat dicapai dengan menggunakan banyak utas?

Iya. Anda tidak dapat menjalankan kode pada banyak CPU atau inti CPU dengan satu utas.

Tanpa banyak CPU / core, utas masih dapat menyederhanakan kode yang secara konseptual berjalan paralel, seperti penanganan klien pada server - tetapi Anda bisa melakukan hal yang sama tanpa utas.

Lumpur
sumber
6

Utas tidak hanya tentang kecepatan tetapi tentang konkurensi.

Jika Anda belum memiliki aplikasi batch seperti yang disarankan @Peter, tetapi sebaliknya toolkit GUI seperti WPF bagaimana Anda dapat berinteraksi dengan pengguna dan logika bisnis hanya dengan satu utas?

Juga, misalkan Anda sedang membangun Server Web. Bagaimana Anda akan melayani lebih dari satu pengguna secara bersamaan hanya dengan satu utas (seandainya tidak ada proses lain)?

Ada banyak skenario di mana hanya satu utas sederhana tidak cukup. Itulah mengapa kemajuan terbaru seperti prosesor Intel MIC dengan lebih dari 50 inti dan ratusan utas sedang berlangsung.

Ya, pemrograman paralel dan bersamaan sulit. Tapi perlu.

Randolf Rincón Fadul
sumber
3
"Hanya satu utas" dapat berarti beberapa hal - Anda dapat menggunakan kelanjutan yang dibatasi untuk mensimulasikan multitasking kooperatif dalam satu utas (OS atau hijau), misalnya.
Frank Shearar
Tentu, tapi saya memberikan sedikit konteks pada pertanyaan @Frank +1 untuk tipnya.
Randolf Rincón Fadul
3
Utas mungkin membuatnya lebih mudah, tetapi semua tugas yang Anda sebutkan dapat dilakukan tanpa utas, dan memang dulu begitu. Misalnya, loop GUI kanonik dulu sementara (true) {proses peristiwa GUI; hitung sedikit}. Tidak perlu utas.
KeithB
Ada webserver single-proses single-threaded. lighttpd misalnya, atau thttpd, atau nginx (meskipun yang terakhir dapat menjalankan lebih dari satu proses, tetapi defaultnya adalah satu. Ia juga selalu single-threaded). Mereka sama sekali tidak punya masalah melayani lebih dari satu pengguna.
StasM
6

Multi-Threading dapat membiarkan antarmuka GUI tetap responsif selama operasi pemrosesan yang lama. Tanpa multi-threading, pengguna akan terjebak menonton formulir yang dikunci saat proses panjang sedang berjalan.

LarsTech
sumber
Itu tidak sepenuhnya benar. Secara teori, Anda dapat membagi operasi panjang Anda menjadi banyak yang lebih kecil dan memperbarui pemrosesan acara di antaranya.
Sebastian Negraszus
@Sebastion N. Tetapi jika proses yang panjang tidak dapat di refactored menjadi yang lebih kecil? Kemampuan untuk menjalankan proses di utas lain dapat membebaskan utas GUI (utas utama) agar tetap responsif.
LarsTech
5

Kode multi-utas dapat menemui jalan buntu logika program dan mengakses data basi dengan cara yang tidak dapat dilakukan utas tunggal.

Utas dapat mengambil bug yang tidak jelas dari sesuatu yang bisa diharapkan oleh programmer rata-rata untuk di-debug dan memindahkannya ke ranah di mana cerita diceritakan tentang keberuntungan yang diperlukan untuk menangkap bug yang sama dengan celana itu turun ketika seorang programmer yang waspada kebetulan melihat hanya pada saat yang tepat.

bmike
sumber
4

aplikasi yang berurusan dengan pemblokiran IO yang juga perlu tetap responsif terhadap input lain (GUI atau koneksi lainnya) tidak dapat dibuat terpisah

penambahan metode pemeriksaan di lib IO untuk melihat berapa banyak yang dapat dibaca tanpa memblokir dapat membantu ini tetapi tidak banyak perpustakaan membuat jaminan penuh tentang ini

ratchet freak
sumber
Mereka dapat di utas tunggal (dan sering kali adalah). Kode memberitahu kernel untuk memulai beberapa IO, dan mendapat sinyal ketika selesai. Sambil menunggu sinyal, ia bisa melakukan pemrosesan lainnya.
KeithB
@ dengan itu bukan non- blokir IO Saya secara khusus mengatakan pemblokiran
ratchet freak
Tetapi mengapa Anda memblokir IO jika Anda ingin tetap responsif? Apakah ada IO pemblokiran yang umumnya tidak memiliki alternatif non-pemblokiran? Saya tidak bisa memikirkan apa pun.
KeithB
@menggunakan RMI java memblokir dan sementara Anda dapat menerapkan callback (tapi itu membuat utas lain) dengan itu tetapi yang dapat diblokir oleh firewall
ratchet freak
Kedengarannya seperti batasan Java RMI, bukan batasan yang melekat pada kode berulir tunggal. Selain itu, jika Anda melakukan RMI, Anda memiliki "utas" eksekusi yang terpisah, hanya pada mesin jarak jauh.
KeithB
4

Banyak jawaban bagus tapi saya tidak yakin frasa seperti itu - Mungkin ini menawarkan cara berbeda untuk melihatnya:

Utas hanyalah penyederhanaan pemrograman seperti Objects atau Aktor atau untuk loop (Ya, apa pun yang Anda implementasikan dengan loop yang dapat Anda implementasikan dengan if / goto).

Tanpa utas Anda cukup menerapkan mesin negara. Saya harus melakukan ini berkali-kali (Pertama kali saya melakukannya saya belum pernah mendengarnya - hanya membuat pernyataan beralih besar dikendalikan oleh variabel "Negara"). Mesin negara masih sangat umum tetapi bisa mengganggu. Dengan benang, sebagian besar pelat ketel hilang.

Mereka juga membuatnya lebih mudah untuk bahasa untuk memecah eksekusi runtime itu menjadi potongan multi-CPU ramah (Begitu juga Aktor, saya percaya).

Java menyediakan utas "Hijau" pada sistem di mana OS tidak menyediakan dukungan threading APA PUN. Dalam hal ini lebih mudah untuk melihat bahwa mereka jelas tidak lebih dari abstraksi pemrograman.

Bill K
sumber
+1 - Threads hanya menyediakan abstraksi untuk paralelisme pada mesin sekuensial pada dasarnya, sama seperti bahasa pemrograman tingkat tinggi menyediakan abstraksi kode mesin.
mouviciel
0

OS menggunakan konsep pengiris waktu di mana setiap utas mendapatkan waktunya untuk dijalankan dan kemudian didahului. Pendekatan seperti itu dapat menggantikan threading seperti yang ada sekarang, tetapi menulis penjadwal Anda sendiri di setiap aplikasi akan berlebihan. Selain itu, Anda harus bekerja dengan perangkat I / O dan sebagainya. Dan akan membutuhkan beberapa dukungan dari sisi perangkat keras, sehingga Anda dapat memecat interupsi untuk membuat penjadwal Anda berjalan. Pada dasarnya Anda akan menulis OS baru setiap saat.

Secara umum threading dapat meningkatkan kinerja jika benang menunggu I / O, atau sedang tidur. Ini juga memungkinkan Anda untuk membuat antarmuka yang responsif, dan memungkinkan proses berhenti, saat Anda melakukan tugas yang panjang. Dan juga, threading meningkatkan hal-hal pada CPU multicore sejati.

Coder
sumber
0

Pertama, utas dapat melakukan dua atau lebih hal sekaligus (jika Anda memiliki lebih dari satu inti). Meskipun Anda juga dapat melakukan ini dengan beberapa proses, beberapa tugas tidak terdistribusi lebih dari beberapa proses dengan sangat baik.

Juga, beberapa tugas memiliki ruang di dalamnya yang tidak dapat Anda hindari dengan mudah. Misalnya, sulit untuk membaca data dari file pada disk dan juga meminta proses Anda melakukan hal lain pada saat yang bersamaan. Jika tugas Anda tentu membutuhkan banyak membaca data dari disk, proses Anda akan menghabiskan banyak waktu menunggu disk tidak peduli apa yang Anda lakukan.

Kedua, utas dapat memungkinkan Anda untuk menghindari mengoptimalkan sejumlah besar kode Anda yang tidak kritis terhadap kinerja. Jika Anda hanya memiliki utas tunggal, setiap bagian kode sangat penting kinerjanya. Jika blok, Anda tenggelam - tidak ada tugas yang akan dilakukan oleh proses yang dapat membuat kemajuan. Dengan utas, blok hanya akan memengaruhi utas itu dan utas lainnya dapat muncul dan bekerja pada tugas yang perlu dilakukan oleh proses itu.

Contoh yang baik adalah kode penanganan kesalahan yang jarang dieksekusi. Katakanlah suatu tugas menjumpai kesalahan yang sangat jarang terjadi dan kode untuk menangani kesalahan itu perlu dimasukkan ke dalam memori. Jika disk sibuk, dan proses hanya memiliki satu utas, tidak ada kemajuan maju dapat dibuat sampai kode untuk menangani kesalahan itu dapat dimuat ke dalam memori. Ini dapat menyebabkan respons meledak-ledak.

Contoh lain adalah jika Anda sangat jarang harus melakukan pencarian basis data. Jika Anda menunggu database membalas, kode Anda akan mengalami penundaan yang sangat lama. Tetapi Anda tidak ingin repot membuat semua kode ini tidak sinkron karena sangat jarang Anda perlu melakukan pencarian ini. Dengan utas untuk melakukan pekerjaan ini, Anda mendapatkan yang terbaik dari kedua dunia. Utas untuk melakukan pekerjaan ini menjadikannya bukan kinerja yang penting sebagaimana mestinya.

David Schwartz
sumber