Apa itu coroutine?

204

Apa itu coroutine? Bagaimana mereka terkait dengan konkurensi?

yesraaj
sumber
2
Kode konkuren tidak harus harus berjalan dalam "paralel" (mari kita tidak memperkenalkan istilah baru).
lucid_dreamer
2
Saya telah menulis satu pustaka coroutine dengan standar C, mendukung pesan select / poll / eplll / kqueue / iocp / Win GUI untuk Linux, BSD dan Windows. Ini adalah proyek open-source di github.com/acl-dev/libfiber . Nasihat akan bermanfaat.
ShuXin Zheng
Info lebih menarik di sini: stackoverflow.com/q/16951904/14357
spender
Saya bisa membayangkan pertanyaan ini akan diturunkan jika diajukan pada era saat ini. Tidak yakin mengapa ada perbedaan persepsi masyarakat yang begitu besar dibandingkan sebelumnya?
tnkh
sebuah coroutine adalah fungsi yang dapat menangguhkan pelaksanaannya sebelum mencapai kembali, dan secara tidak langsung dapat melewati kontrol ke coroutine lain untuk beberapa waktu.
hassanzadeh.sd

Jawaban:

138

Coroutine dan concurrency sebagian besar bersifat orthogonal. Coroutine adalah struktur kontrol umum di mana kontrol aliran secara kooperatif dilewatkan di antara dua rutinitas yang berbeda tanpa kembali.

Pernyataan 'hasil' dalam Python adalah contoh yang baik. Itu menciptakan coroutine. Ketika 'hasil' ditemui, keadaan fungsi saat ini disimpan dan kontrol dikembalikan ke fungsi pemanggilan. Fungsi panggilan kemudian dapat mentransfer eksekusi kembali ke fungsi menghasilkan dan statusnya akan dikembalikan ke titik di mana 'hasil' ditemukan dan eksekusi akan berlanjut.

pengguna21714
sumber
19
Apa perbedaan antara memanggil fungsi secara langsung dan menghasilkan dari coroutine dengan membungkus fungsi ini ke coroutine ini?
Ming Li
3
Mungkin lebih baik untuk menjelaskan bahwa kedua konsep ini tidak benar-benar 'ortogonal' dalam konteks ini. Anda pasti bisa menggambar bagaimana kedua konsep itu mirip satu sama lain. Gagasan kontrol lewat antara dua hal atau lebih sangat mirip.
steviejay
8
Coroutines are a general control structure whereby flow control is cooperatively passed between two different routines without returning.<- ini adalah konkurensi. Kata yang Anda cari adalah paralelisme.
Adam Arold
@steviejay orthogonal = Not similar to each other?
tonix
1
@tonix saya diberitahu itu orthogonalberarti "tidak tergantung satu sama lain".
Rick
77

Dari Pemrograman di Lua , Coroutinesbagian " ":

Coroutine mirip dengan utas (dalam arti multithreading): itu adalah garis eksekusi, dengan tumpukan sendiri, variabel lokalnya sendiri, dan penunjuk instruksinya sendiri; tetapi berbagi variabel global dan sebagian besar hal lain dengan coroutine lain. Perbedaan utama antara utas dan coroutine adalah, secara konseptual (atau secara harfiah, dalam mesin multiprosesor), program dengan utas menjalankan beberapa utas secara paralel. Coroutine, di sisi lain, bersifat kolaboratif: pada waktu tertentu, sebuah program dengan coroutine hanya menjalankan salah satu dari coroutine-nya, dan coroutine yang berjalan ini menangguhkan pelaksanaannya hanya ketika secara eksplisit meminta untuk ditangguhkan.

Jadi intinya adalah: Coroutine adalah "kolaboratif". Bahkan dalam sistem multi-core, hanya ada satu coroutine yang berjalan pada waktu tertentu (tetapi beberapa thread dapat berjalan secara paralel). Ada non-preemptive antara coroutine, coroutine yang berjalan harus melepaskan eksekusi secara eksplisit.

Untuk " concurrency", Anda dapat merujuk slide Rob Pike :

Concurrency adalah komposisi dari komputasi yang dieksekusi secara independen.

Jadi selama eksekusi coroutine A, ia melewati kontrol ke coroutine B. Kemudian setelah beberapa waktu, coroutine B melewati kontrol kembali ke coroutine A. Karena ada ketergantungan antara coroutine, dan mereka harus berjalan bersama-sama, sehingga dua coroutine tidak konkurensi .

Nan Xiao
sumber
6
Coroutine tidak dieksekusi secara independen. Mereka bergiliran, masing-masing menunggu yang lain untuk melakukan beberapa bagian dari pekerjaan. Mereka secara aktif berkoordinasi satu sama lain. Itulah kebalikan dari definisi konkurensi Rob Pikes.
Erick G. Hagstrom
2
@ ErickG.Hagstrom: Meskipun mereka tidak mengeksekusi secara independen, logika setiap coroutine bisa mandiri, kan? Jika benar, itu seperti OS yang tidak preemptive yang berjalan pada CPU satu inti, satu proses harus melepaskan CPU untuk membiarkan tugas lain berjalan.
Nan Xiao
6
Ada perbedaan antara melepaskan CPU untuk membiarkan beberapa tugas lain berjalan, dan memberi tahu beberapa proses spesifik lainnya yang sudah waktunya untuk dijalankan. Coroutine melakukan yang terakhir. Itu tidak independen dalam arti apa pun.
Erick G. Hagstrom
7
@ChrisClark Saya setuju dengan Anda. Coroutine adalah konkurensi. Berikut ini beberapa kutipan dari wikipedia: Coroutine sangat mirip dengan utas. Namun, coroutine bekerja sama multitasking, sedangkan utas biasanya multitasking. Ini berarti mereka memberikan konkurensi tetapi bukan paralelisme .
smwikipedia
3
Dan: Multitasking kooperatif, juga dikenal sebagai multitasking non-preemptive, adalah gaya multitasking komputer di mana sistem operasi tidak pernah memulai perubahan konteks dari proses yang sedang berjalan ke proses lain. Sebagai gantinya, proses secara sukarela menghasilkan kontrol secara berkala atau ketika idle atau diblokir secara logis untuk memungkinkan beberapa aplikasi dijalankan secara bersamaan.
smwikipedia
47

Saya menemukan sebagian besar jawaban terlalu teknis walaupun itu adalah pertanyaan teknis. Saya mengalami kesulitan mencoba memahami proses coroutine. Saya agak mendapatkannya tetapi kemudian saya tidak mendapatkannya pada saat yang sama.

Saya menemukan jawaban ini di sini sangat membantu:

https://dev.to/thibmaek/explain-coroutines-like-im-five-2d9

Mengutip dari Idan Arye:

Untuk membangun cerita Anda, saya akan menuliskannya seperti ini:

Anda mulai menonton kartun, tetapi intro. Alih-alih menonton intro Anda beralih ke permainan dan memasuki lobi online - tetapi itu membutuhkan 3 pemain dan hanya Anda dan kakak Anda yang ada di dalamnya. Alih-alih menunggu pemain lain bergabung, Anda beralih ke pekerjaan rumah, dan jawab pertanyaan pertama. Pertanyaan kedua memiliki tautan ke video YouTube yang perlu Anda tonton. Anda membukanya - dan mulai memuat. Alih-alih menunggu untuk memuat, Anda beralih kembali ke kartun. Intro sudah berakhir, jadi Anda bisa menonton. Sekarang ada iklan - tetapi sementara pemain ketiga telah bergabung sehingga Anda beralih ke permainan Dan seterusnya ...

Idenya adalah Anda tidak hanya beralih tugas dengan sangat cepat agar terlihat seperti Anda melakukan semuanya sekaligus. Anda memanfaatkan waktu Anda menunggu sesuatu terjadi (IO) untuk melakukan hal-hal lain yang memang membutuhkan perhatian langsung Anda.

Pasti memeriksa tautannya, ada banyak lagi yang saya tidak bisa kutip semuanya.

mr1031011
sumber
6
Ilustrasi yang sangat sederhana dan mudah. +1 untuk ini.
Taslim Oseni
ilustrasi yang bagus. Saya membangun cerita serupa - dengan mengantre menunggu untuk mengumpulkan paket. tapi untuk hari ini, milikmu jauh lebih realistis, siapa yang mengantre ketika ada pengiriman door2door? Lol
apolak
1
Itu penjelasan yang luar biasa. Dari kutipan itu sendiri, sangat jelas.
Farruh Habibullaev
15

Coroutine mirip dengan subrutin / utas. Perbedaannya adalah begitu pemanggil memanggil subrutin / utas, itu tidak akan pernah kembali ke fungsi pemanggil. Tetapi coroutine dapat kembali ke pemanggil setelah mengeksekusi beberapa kode yang memungkinkan pemanggil untuk mengeksekusi beberapa kode sendiri dan kembali ke titik coroutine di mana ia menghentikan eksekusi dan melanjutkan dari sana. yaitu. Coroutine memiliki lebih dari satu titik masuk dan keluar

Kelip
sumber
Tidak begitu mirip dengan utas - yang berjalan secara independen dan simultan (memisahkan inti secara paralel). Selain itu perbandingan subrutin gagal dalam arti bahwa ada beberapa jalur eksekusi independen dan mereka tidak mengembalikan hasil satu sama lain.
javadba
11
  • Coroutine adalah fitur hebat yang tersedia dalam Bahasa Kotlin
  • Coroutine adalah cara baru untuk menulis kode asinkron, non-pemblokiran (dan banyak lagi)
  • Coroutine adalah benang yang ringan. Utas yang ringan berarti tidak memetakan pada utas asli, sehingga tidak memerlukan pengaktifan konteks pada prosesor, sehingga lebih cepat.
  • tidak memetakan di utas asli
  • Coroutine dan utas keduanya multitasking. Tetapi perbedaannya adalah bahwa utas dikelola oleh OS dan coroutine oleh pengguna.

Pada dasarnya, ada dua jenis Coroutine:

  1. Tanpa tumpukan
  2. Stackful

Kotlin mengimplementasikan coroutine stackless - itu artinya coroutine tidak memiliki stack sendiri, sehingga mereka tidak memetakan pada thread asli.

Ini adalah fungsi untuk memulai coroutine:

launch{}

async{}

Anda dapat belajar lebih banyak dari sini:

https://www.kotlindevelopment.com/deep-dive-coroutines/

https://blog.mindorks.com/what-are-coroutines-in-kotlin-bf4fecd476e9

Dhaval Jivani
sumber
1
Jawaban yang bagus! Berguna untuk pengembang Kotlin dan Android.
Malwinder Singh
5

Pada catatan yang berbeda, dalam geventpustaka python adalah pustaka coroutinejaringan berbasis yang memberi Anda fitur mirip-mirip seperti permintaan jaringan async, tanpa overhead untuk membuat dan menghancurkan utas. The coroutinelibrary yang digunakan adalah greenlet.

Joseph
sumber
2

Dari Python Coroutine :

Eksekusi coroutine Python dapat ditunda dan dilanjutkan di banyak titik (lihat coroutine). Di dalam tubuh fungsi coroutine, menunggu dan pengidentifikasi async menjadi kata kunci yang dipesan; menunggu ekspresi, async untuk dan async dengan hanya dapat digunakan dalam fungsi tubuh coroutine.

Dari Coroutines (C ++ 20)

Coroutine adalah fungsi yang dapat menunda eksekusi untuk dilanjutkan nanti . Coroutine tidak bertumpuk: mereka menunda eksekusi dengan kembali ke pemanggil. Hal ini memungkinkan untuk kode sekuensial yang dieksekusi secara asinkron (misalnya untuk menangani I / O non-blocking tanpa panggilan balik eksplisit), dan juga mendukung algoritma pada urutan tak terbatas yang dihitung malas dan penggunaan lainnya.

Bandingkan dengan jawaban orang lain:

Menurut pendapat saya, bagian yang dilanjutkan kemudian adalah perbedaan inti, seperti halnya @ Twinkle.
Meskipun banyak bidang dokumen masih dalam proses, bagian ini mirip dengan sebagian besar jawaban, kecuali @Nan Xiao.

Coroutine, di sisi lain, bersifat kolaboratif: pada waktu tertentu, sebuah program dengan coroutine hanya menjalankan salah satu dari coroutine-nya, dan coroutine yang berjalan ini menangguhkan pelaksanaannya hanya ketika secara eksplisit meminta untuk ditangguhkan.

Karena itu dikutip dari Program in Lua, mungkin itu terkait bahasa (tidak akrab dengan Lua saat ini), tidak semua dokumen menyebutkan hanya satu bagian.

Hubungannya dengan konkuren:
Ada bagian "Eksekusi" dari Coroutine (C ++ 20). Terlalu lama untuk mengutip di sini.
Selain detailnya, ada beberapa negara.

When a coroutine begins execution  
When a coroutine reaches a suspension point  
When a coroutine reaches the co_return statement  
If the coroutine ends with an uncaught exception  
When the coroutine state is destroyed either because it terminated via co_return or uncaught exception, or because it was destroyed via its handle 

sebagai komentar dari @Adam Arold di bawah jawaban @ user217714. Ini konkurensi.
Tapi ini berbeda dari multithreading. dari std :: thread

Utas memungkinkan beberapa fungsi untuk dieksekusi secara bersamaan. Utas memulai eksekusi segera setelah konstruksi objek utas terkait (sambil menunggu penundaan penjadwalan OS), mulai dari fungsi tingkat atas yang disediakan sebagai argumen konstruktor. Nilai kembalinya fungsi tingkat atas diabaikan dan jika itu berakhir dengan melemparkan pengecualian, std :: terminate disebut. Fungsi tingkat atas dapat mengkomunikasikan nilai kembali atau pengecualian ke pemanggil melalui std :: janji atau dengan memodifikasi variabel yang dibagi (yang mungkin memerlukan sinkronisasi, lihat std :: mutex dan std :: atomic)

Karena ini adalah konkurensi, ia berfungsi seperti multithreading terutama ketika menunggu tidak dapat dihindari (dari perspektif OS), itu juga mengapa membingungkan.

Shihe Zhang
sumber
1

Coroutine adalah jenis khusus dari subprogram. Daripada hubungan master-slave antara penelepon dan subprogram yang disebut yang ada dengan subprogram konvensional, penelepon dan yang disebut coroutine lebih adil.

  • Coroutine adalah subprogram yang memiliki banyak entri dan mengendalikannya sendiri - didukung langsung di Lua

  • Juga disebut kontrol simetris: pemanggil dan yang disebut coroutine memiliki basis yang lebih setara

  • Panggilan coroutine dinamai resume

  • Resume pertama dari coroutine adalah untuk permulaan, tetapi panggilan berikutnya masuk pada titik tepat setelah pernyataan yang dieksekusi terakhir di coroutine

  • Coroutine berulang kali saling melanjutkan, mungkin selamanya

  • Coroutine menyediakan eksekusi kuasi-konkuren dari unit program (coroutine); eksekusi mereka disisipkan, tetapi tidak tumpang tindih

Contoh 1 Contoh2

BoraKurucu
sumber
1

Saya menemukan penjelasan dari tautan ini cukup mudah. Tidak ada jawaban yang mencoba menjelaskan konkurensi vs paralelisme kecuali titik terakhir dalam jawaban ini .

  1. apa yang bersamaan (program)?

dikutip dari "pemrograman Erlang", oleh Joe Armstrong, sang legendaris:

sebuah program bersamaan dapat berjalan secara potensial lebih cepat pada komputer paralel.

  • program bersamaan adalah program yang ditulis dalam bahasa pemrograman bersamaan. Kami menulis program bersamaan untuk alasan kinerja, skalabilitas, atau toleransi kesalahan.

  • bahasa pemrograman konkuren adalah bahasa yang memiliki konstruksi bahasa eksplisit untuk menulis program bersamaan. Konstruksi ini merupakan bagian integral dari bahasa pemrograman dan berperilaku dengan cara yang sama pada semua sistem operasi.

  • komputer paralel adalah komputer yang memiliki beberapa unit pemrosesan (CPU atau inti) yang dapat berjalan secara bersamaan.

Jadi konkurensi tidak sama dengan paralelisme. Anda masih dapat menulis program bersamaan pada komputer inti tunggal. Penjadwal pembagian waktu akan membuat Anda merasa program Anda berjalan secara bersamaan.

Program bersamaan memiliki potensi untuk berjalan secara paralel di komputer paralel tetapi tidak dijamin . OS hanya dapat memberi Anda satu inti untuk menjalankan program Anda.

Oleh karena itu, concurrency adalah model perangkat lunak dari program bersamaan yang tidak berarti program Anda dapat berjalan secara paralel secara fisik.

  1. coroutine dan concurrency

Kata "coroutine" terdiri dari dua kata: "co" (kooperatif) dan "rutinitas" (fungsi).

Sebuah. apakah itu mencapai konkurensi atau paralelisme?

Sederhananya, mari kita bahas pada komputer inti tunggal .

Concurrency dicapai dengan pembagian waktu dari OS. Utas menjalankan kode dalam kerangka waktu yang ditentukan pada inti CPU. Itu bisa didahului oleh OS. Ini juga dapat menghasilkan kontrol ke OS.

Coroutine, di sisi lain, menghasilkan kontrol ke coroutine lain di dalam utas, bukan ke OS. Jadi semua coroutine dalam utas masih mengeksploitasi kerangka waktu untuk utas itu tanpa menghasilkan inti CPU ke utas lain yang dikelola oleh OS.

Oleh karena itu, Anda dapat memikirkan coroutine yang mencapai pembagian waktu oleh pengguna bukan oleh OS (atau kuasi-paralelisme). Coroutine berjalan pada inti yang sama yang ditugaskan ke utas yang menjalankan coroutine tersebut.

Apakah Coroutine mencapai paralelisme? Jika itu adalah kode yang terikat CPU, tidak. Seperti pembagian waktu, itu membuat Anda merasa mereka berjalan secara paralel tetapi eksekusi mereka disisipkan tidak tumpang tindih. Jika terikat IO, ya, ia mencapai paralel dengan perangkat keras (perangkat IO) bukan oleh kode Anda.

b. bedanya dengan pemanggilan fungsi?

masukkan deskripsi gambar di sini

Seperti yang ditunjukkan gambar, tidak perlu menelepon returnuntuk beralih kontrol. Itu bisa menghasilkan tanpa return. Coroutine menyimpan dan membagikan status pada bingkai fungsi saat ini (tumpukan). Jadi ini jauh lebih ringan daripada fungsi karena Anda tidak perlu menyimpan register dan variabel lokal untuk ditumpuk dan mundur saat panggilan call ret.

Izana
sumber
0

Saya akan memperluas jawaban @ user21714. Coroutine adalah jalur eksekusi independen yang tidak dapat berjalan secara bersamaan. Mereka bergantung pada pengontrol - misalnya pythonperpustakaan pengontrol - untuk menangani peralihan di antara jalur ini. Tetapi agar ini bisa berhasil, coroutine sendiri perlu dipanggilyield atau struktur serupa yang memungkinkan eksekusi mereka dijeda.

Threads sebaliknya berjalan pada sumber daya komputasi independen dan secara paralel satu sama lain. Karena mereka menggunakan sumber daya yang berbeda, maka tidak perlu meminta imbal hasil untuk memungkinkan jalan eksekusi lainnya berjalan.

Anda dapat melihat efek ini dengan memulai program multihreaded - misalnya jvmaplikasi - di mana kedelapan core i7core hyperthread Anda digunakan: Anda mungkin melihat utilisasi 797% pada Activity Monitoratau Top. Alih-alih saat menjalankan pythonprogram biasa - bahkan program dengan coroutinesatau python threading- pemanfaatannya akan maksimal 100%. Yaitu satu mesin hyperthread.

javadba
sumber