Apa perbedaan antara panggilan asinkron dan non-pemblokiran? Juga antara memblokir dan panggilan sinkron (dengan contoh harap)?
Apa perbedaan antara panggilan asinkron dan non-pemblokiran? Juga antara memblokir dan panggilan sinkron (dengan contoh harap)?
Jawaban:
Dalam banyak keadaan mereka berbeda nama untuk hal yang sama, tetapi dalam beberapa konteks mereka sangat berbeda. Jadi itu tergantung. Terminologi tidak diterapkan secara konsisten di seluruh industri perangkat lunak.
Misalnya dalam API soket klasik, soket non-pemblokiran adalah soket yang segera kembali dengan pesan kesalahan khusus "akan memblokir", sedangkan soket pemblokir akan diblokir. Anda harus menggunakan fungsi terpisah seperti select
atau poll
untuk mencari tahu kapan waktu yang tepat untuk mencoba lagi.
Tetapi soket asinkron (seperti yang didukung oleh soket Windows), atau pola IO asinkron yang digunakan dalam .NET, lebih nyaman. Anda memanggil metode untuk memulai operasi, dan kerangka kerja memanggil Anda kembali setelah selesai. Bahkan di sini, ada perbedaan mendasar. Asynchronous Win32 soket "marshal" hasil mereka ke utas GUI tertentu dengan melewati pesan Window, sedangkan .NET asynchronous IO bebas-utas (Anda tidak tahu utas apa panggilan balik Anda akan dipanggil).
Jadi mereka tidak selalu berarti hal yang sama. Untuk menyaring contoh soket, kita dapat mengatakan:
sinkron / asinkron adalah menggambarkan hubungan antara dua modul.
blocking / non-blocking adalah untuk menggambarkan situasi satu modul.
Contoh:
Modul X: "I".
Modul Y: "toko buku".
X bertanya pada Y: apakah Anda memiliki buku berjudul "c ++ primer"?
1) pemblokiran: sebelum Y menjawab X, X terus menunggu jawaban di sana. Sekarang X (satu modul) sedang memblokir. X dan Y adalah dua utas atau dua proses atau satu utas atau satu proses? kami tidak tahu.
2) non-blocking: sebelum Y menjawab X, X hanya pergi dan melakukan hal-hal lain. X dapat kembali setiap dua menit untuk memeriksa apakah Y telah menyelesaikan tugasnya? Atau X tidak akan kembali sampai Y memanggilnya? Kami tidak tahu. Kita hanya tahu bahwa X dapat melakukan hal-hal lain sebelum Y menyelesaikan tugasnya. Di sini X (satu modul) adalah non-blocking. X dan Y adalah dua utas atau dua proses atau satu proses? kami tidak tahu. TAPI kami yakin bahwa X dan Y tidak dapat menjadi satu utas.
3) sinkron: sebelum Y menjawab X, X terus menunggu jawaban di sana. Ini berarti bahwa X tidak dapat melanjutkan sampai Y menyelesaikan tugasnya. Sekarang kita katakan: X dan Y (dua modul) sinkron. X dan Y adalah dua utas atau dua proses atau satu utas atau satu proses? kami tidak tahu.
4) asinkron: sebelum Y menjawab X, X pergi ke sana dan X dapat melakukan pekerjaan lain. X tidak akan kembali sampai Y memanggilnya. Sekarang kita katakan: X dan Y (dua modul) asinkron. X dan Y adalah dua utas atau dua proses atau satu proses? kami tidak tahu. TAPI kami yakin bahwa X dan Y tidak dapat menjadi satu utas.
Mohon perhatikan dua kalimat tebal di atas. Mengapa kalimat tebal dalam 2) berisi dua kasus sedangkan kalimat tebal dalam 4) hanya berisi satu kasus? Ini adalah kunci perbedaan antara non-blocking dan asynchronous.
Berikut adalah contoh umum tentang non-pemblokiran & sinkron:
// thread X
while (true)
{
msg = recv(Y, NON_BLOCKING_FLAG);
if (msg is not empty)
{
break;
}
sleep(2000); // 2 sec
}
// thread Y
// prepare the book for X
send(X, book);
Anda dapat melihat bahwa desain ini adalah non-blocking (Anda dapat mengatakan bahwa sebagian besar waktu loop ini melakukan sesuatu yang tidak masuk akal tetapi di mata CPU, X sedang berjalan, yang berarti X adalah non-blocking) sedangkan X dan Y adalah sinkron karena X dapat dapat terus melakukan hal-hal lain (X tidak dapat melompat keluar dari loop) sampai mendapat buku dari Y.
Biasanya dalam kasus ini, membuat X blocking jauh lebih baik karena non-blocking menghabiskan banyak sumber daya untuk loop bodoh. Tetapi contoh ini bagus untuk membantu Anda memahami fakta: non-blocking tidak berarti asinkron.
Keempat kata memang membuat kita mudah bingung, yang harus kita ingat adalah bahwa keempat kata tersebut berfungsi untuk desain arsitektur. Mempelajari cara mendesain arsitektur yang baik adalah satu-satunya cara untuk membedakannya.
Sebagai contoh, kami dapat merancang semacam arsitektur:
// Module X = Module X1 + Module X2
// Module X1
while (true)
{
msg = recv(many_other_modules, NON_BLOCKING_FLAG);
if (msg is not null)
{
if (msg == "done")
{
break;
}
// create a thread to process msg
}
sleep(2000); // 2 sec
}
// Module X2
broadcast("I got the book from Y");
// Module Y
// prepare the book for X
send(X, book);
Dalam contoh di sini, kita dapat mengatakan itu
Jika perlu, Anda juga dapat menjelaskan utas yang dibuat dalam X1 dengan empat kata.
Hal yang lebih penting adalah: kapan kita menggunakan sinkron dan bukan asinkron? kapan kita menggunakan pemblokiran alih-alih non-pemblokiran?
Mengapa Nginx non-blocking? Mengapa Apache diblokir?
Untuk membuat pilihan yang baik, Anda harus menganalisis kebutuhan Anda dan menguji kinerja berbagai arsitektur. Tidak ada arsitektur seperti itu yang cocok untuk berbagai kebutuhan.
Menempatkan pertanyaan ini dalam konteks NIO dan NIO.2 di java 7, async IO adalah satu langkah lebih maju daripada non-blocking. Dengan panggilan non-blocking java NIO, seseorang akan mengatur semua saluran (SocketChannel, ServerSocketChannel, FileChannel, dll) dengan menelepon AbstractSelectableChannel.configureBlocking(false)
. Namun, setelah panggilan IO itu kembali, Anda kemungkinan masih perlu mengontrol cek seperti jika dan kapan harus membaca / menulis lagi, dll.
Misalnya,
while (!isDataEnough()) {
socketchannel.read(inputBuffer);
// do something else and then read again
}
Dengan api asinkron di java 7, kontrol ini dapat dibuat dengan cara yang lebih fleksibel. Salah satu dari 2 cara tersebut adalah menggunakan CompletionHandler
. Perhatikan bahwa kedua read
panggilan tidak menghalangi.
asyncsocket.read(inputBuffer, 60, TimeUnit.SECONDS /* 60 secs for timeout */,
new CompletionHandler<Integer, Object>() {
public void completed(Integer result, Object attachment) {...}
public void failed(Throwable e, Object attachment) {...}
}
}
FileChannel
tidak dapat dipilih dan tidak dapat dikonfigurasi untuk non-pemblokiran.
Seperti yang mungkin Anda lihat dari banyak jawaban yang berbeda (dan seringkali saling terpisah), itu tergantung pada siapa Anda bertanya. Di beberapa arena, istilah ini sama. Atau mereka masing-masing dapat merujuk pada dua konsep serupa:
Dalam kedua kasus tersebut, tujuannya adalah untuk memungkinkan program untuk tidak diblokir menunggu proses yang lambat untuk menyelesaikan - bagaimana program diharapkan merespons adalah satu-satunya perbedaan nyata. Istilah yang merujuk pada yang juga berubah dari programmer ke programmer, bahasa ke bahasa, atau platform ke platform. Atau istilah dapat merujuk ke konsep yang sama sekali berbeda (seperti penggunaan sinkron / asinkron dalam kaitannya dengan pemrograman utas).
Maaf, tapi saya tidak percaya ada satu jawaban benar yang secara global benar.
Sebuah nonblocking panggilan kembali segera dengan data apa saja yang ada: jumlah penuh byte yang diminta, lebih sedikit, atau tidak sama sekali.
Sebuah asynchronous panggilan meminta transfer yang akan dilakukan dalam Surat keseluruhan (keseluruhan) tapi akan menyelesaikan di beberapa waktu mendatang.
Non-blocking: Fungsi ini tidak akan menunggu saat di stack.
Asinkron: Pekerjaan dapat dilanjutkan atas nama panggilan fungsi setelah panggilan tersebut meninggalkan tumpukan
Sinkron didefinisikan sebagai terjadi pada saat yang bersamaan.
Asinkron didefinisikan sebagai tidak terjadi pada saat yang bersamaan.
Inilah yang menyebabkan kebingungan pertama. Sinkron sebenarnya adalah apa yang dikenal sebagai paralel. Sementara asinkron berurutan, lakukan ini, lalu lakukan itu.
Sekarang seluruh masalahnya adalah tentang pemodelan perilaku asinkron, karena Anda memiliki beberapa operasi yang memerlukan respons dari yang lain sebelum dapat dimulai. Jadi ini masalah koordinasi, bagaimana Anda tahu bahwa Anda sekarang dapat memulai operasi itu?
Solusi paling sederhana dikenal sebagai pemblokiran.
Memblokir adalah ketika Anda hanya memilih untuk menunggu hal lain dilakukan dan mengembalikan respons Anda sebelum beralih ke operasi yang membutuhkannya.
Jadi jika Anda perlu menaruh mentega pada roti panggang, maka Anda harus terlebih dahulu memanggang roti tersebut. Cara Anda mengoordinasikannya adalah pertama-tama Anda akan memanggang roti tersebut, lalu menatap pemanggang roti tanpa henti sampai roti itu muncul, dan kemudian Anda akan melanjutkan memakainya.
Ini solusi paling sederhana, dan bekerja dengan sangat baik. Tidak ada alasan kuat untuk tidak menggunakannya, kecuali Anda kebetulan juga memiliki hal-hal lain yang perlu Anda lakukan yang tidak memerlukan koordinasi dengan operasi. Misalnya, mencuci piring. Mengapa menunggu menganggur menatap pemanggang roti terus-menerus sampai roti panggang muncul, ketika Anda tahu itu akan memakan waktu, dan Anda bisa mencuci seluruh piring saat selesai?
Di situlah dua solusi lain yang dikenal masing-masing sebagai non-blocking dan asinkron ikut bermain.
Non-pemblokiran adalah ketika Anda memilih untuk melakukan hal-hal yang tidak terkait lainnya sambil menunggu operasi selesai. Memeriksa kembali ketersediaan respons yang Anda inginkan.
Jadi, bukannya melihat pemanggang untuk pop. Anda pergi dan mencuci seluruh piring. Dan kemudian Anda mengintip pemanggang untuk melihat apakah pemanggang telah muncul. Jika tidak, Anda pergi mencuci piring lain, memeriksa kembali di pemanggang di antara setiap hidangan. Ketika Anda melihat roti panggang muncul, Anda berhenti mencuci piring, dan alih-alih Anda mengambil roti panggang dan melanjutkan untuk menaruh mentega di atasnya.
Meski harus terus-menerus memeriksa roti panggang bisa menyebalkan, bayangkan pemanggang roti ada di ruangan lain. Di sela-sela hidangan Anda membuang waktu Anda pergi ke ruangan lain untuk memeriksa roti panggang.
Di sinilah asinkron.
Asynchronous adalah ketika Anda memilih untuk melakukan hal-hal yang tidak terkait lainnya saat Anda menunggu operasi selesai. Alih-alih memeriksanya, Anda mendelegasikan pekerjaan memeriksa ke sesuatu yang lain, bisa jadi operasi itu sendiri atau pengamat, dan Anda memiliki hal itu memberi tahu dan mungkin menginterupsi Anda ketika respons tersedia sehingga Anda dapat melanjutkan ke operasi lain yang membutuhkannya.
Terminologi yang aneh. Tidak masuk akal, karena semua solusi ini adalah cara untuk membuat koordinasi asinkron dari tugas-tugas dependen. Itu sebabnya saya lebih suka menyebutnya evented.
Jadi untuk yang ini, Anda memutuskan untuk meningkatkan pemanggang roti Anda sehingga berbunyi bip saat bersulang. Anda terus-menerus mendengarkan, bahkan saat Anda sedang mencuci piring. Saat mendengar bunyi bip, Anda mengantri dalam ingatan Anda bahwa segera setelah Anda selesai mencuci piring Anda saat ini, Anda akan berhenti dan memasukkan mentega ke atas roti panggang. Atau Anda bisa memilih untuk menghentikan mencuci piring saat ini, dan langsung berurusan dengan roti panggang.
Jika Anda kesulitan mendengar bunyi bip, Anda dapat meminta pasangan Anda menonton pemanggang untuk Anda, dan datang memberi tahu Anda ketika roti panggang sudah siap. Pasangan Anda sendiri dapat memilih salah satu dari tiga strategi di atas untuk mengoordinasikan tugasnya mengawasi pemanggang roti dan memberi tahu Anda kapan mereka siap.
Pada catatan terakhir, ada baiknya untuk memahami bahwa sementara non-blocking dan async (atau apa yang saya lebih suka panggil dengan nama) memungkinkan Anda untuk melakukan hal-hal lain sambil menunggu, Anda tidak harus melakukannya juga. Anda dapat memilih untuk terus mengulang memeriksa status panggilan yang tidak menghalangi, tidak melakukan apa pun. Itu sering lebih buruk daripada memblokir (seperti melihat pemanggang roti, lalu pergi, lalu kembali sampai selesai), jadi banyak API non-pemblokiran memungkinkan Anda untuk beralih ke mode pemblokiran darinya. Untuk acara, Anda bisa menunggu sampai Anda diberitahu. Kelemahan dalam hal itu adalah bahwa menambahkan pemberitahuan itu rumit dan berpotensi mahal untuk memulai. Anda harus membeli pemanggang roti baru dengan fungsi bip, atau meyakinkan pasangan Anda untuk menontonnya untuk Anda.
Dan satu hal lagi, Anda perlu menyadari trade off yang disediakan ketiganya. Yang satu jelas tidak lebih baik dari yang lain. Pikirkan contoh saya. Jika pemanggang Anda begitu cepat, Anda tidak akan punya waktu untuk mencuci piring, bahkan tidak mulai mencuci, itulah cara pemanggang Anda. Memulai sesuatu yang lain dalam kasus itu hanyalah buang-buang waktu dan usaha. Memblokir akan berhasil. Demikian pula, jika mencuci piring akan memakan waktu 10 kali lebih lama dari pemanggangan. Anda harus bertanya pada diri sendiri apa yang lebih penting untuk dilakukan? Roti bakar mungkin menjadi dingin dan keras pada saat itu, tidak sepadan, memblokir juga akan dilakukan. Atau Anda harus memilih hal-hal yang lebih cepat untuk dilakukan sambil menunggu. Ada lebih jelas, tetapi jawaban saya sudah cukup lama, poin saya adalah Anda harus memikirkan semua itu, dan kompleksitas penerapan masing-masing untuk memutuskan apakah itu layak, dan apakah itu '
Edit:
Meskipun ini sudah lama, saya juga ingin ini selesai, jadi saya akan menambahkan dua poin lagi.
1) Ada juga umumnya ada model keempat yang dikenal sebagai multiplexed . Ini adalah saat ketika Anda menunggu satu tugas, Anda memulai yang lain, dan saat Anda menunggu keduanya, Anda memulai satu lagi, dan seterusnya, sampai Anda punya banyak tugas semua dimulai dan kemudian, Anda menunggu, tetapi pada semua mereka. Jadi, segera setelah semuanya selesai, Anda dapat melanjutkan dengan menangani responsnya, dan kemudian kembali menunggu yang lain. Ini dikenal sebagai multiplexed, karena saat Anda menunggu, Anda perlu memeriksa setiap tugas satu demi satu untuk melihat apakah mereka selesai, ad vitam, sampai satu selesai. Ini sedikit ekstensi di atas non-pemblokiran normal.
Dalam contoh kita itu akan seperti memulai pemanggang, kemudian mesin pencuci piring, kemudian microwave, dll. Dan kemudian menunggu salah satu dari mereka. Di mana Anda akan memeriksa pemanggang untuk melihat apakah sudah selesai, jika tidak, Anda akan memeriksa mesin cuci piring, jika tidak, microwave, dan sekitar lagi.
2) Meskipun saya percaya ini adalah kesalahan besar, sinkron sering digunakan untuk mengartikan satu hal dalam satu waktu. Dan asinkron banyak hal sekaligus. Dengan demikian Anda akan melihat pemblokiran sinkron dan non-pemblokiran yang digunakan untuk merujuk pada pemblokiran dan non-pemblokiran. Dan asynchronous blocking dan non-blocking digunakan untuk merujuk pada multiplexed dan evented.
Saya tidak begitu mengerti bagaimana kita sampai di sana. Tetapi ketika datang ke IO dan Komputasi, sinkron dan asinkron sering merujuk pada apa yang lebih dikenal sebagai non-overlap dan overlap. Artinya, asinkron berarti IO dan Komputasi tumpang tindih, alias, terjadi secara bersamaan. Sementara sinkron berarti tidak, sehingga terjadi secara berurutan. Untuk non-blocking yang sinkron, itu berarti Anda tidak memulai IO atau Komputasi lainnya, Anda hanya perlu menunggu dan mensimulasikan panggilan pemblokiran. Saya berharap orang-orang berhenti menyalahgunakan sinkron dan asinkron seperti itu. Jadi saya tidak mendorongnya.
Memblokir panggilan: Kontrol hanya kembali ketika panggilan selesai.
Panggilan tanpa pemblokiran : Kontrol segera kembali. Kemudian OS entah bagaimana memberitahukan proses bahwa panggilan telah selesai.
Program sinkron : Program yang menggunakan Pemblokiran panggilan. Agar tidak membeku selama panggilan, ia harus memiliki 2 utas atau lebih (itu sebabnya ini disebut Sinkron - utas berjalan secara sinkron).
Program asinkron : Program yang menggunakan panggilan Non-blocking . Ini hanya dapat memiliki 1 utas dan masih tetap interaktif.
Mereka berbeda dalam mengeja saja. Tidak ada perbedaan dalam apa yang mereka rujuk. Secara teknis Anda bisa mengatakan mereka berbeda dalam penekanan. Non pemblokiran mengacu pada aliran kontrol (tidak memblokir.) Asinkron mengacu pada saat event \ data ditangani (tidak secara sinkron.)
Model pemblokiran memerlukan aplikasi yang memulai untuk memblokir ketika I / O telah dimulai. Ini berarti bahwa tidak mungkin untuk tumpang tindih pemrosesan dan I / O pada saat yang sama. Model non-blocking yang sinkron memungkinkan tumpang tindih pemrosesan dan I / O, tetapi mengharuskan aplikasi memeriksa status I / O secara berulang. Hal ini menyebabkan I / O non-pemblokiran tidak sinkron, yang memungkinkan tumpang tindih pemrosesan dan I / O, termasuk pemberitahuan penyelesaian I / O.
Pemblokiran: kontrol kembali ke memanggil presesi setelah pemrosesan selesai primitif (sinkronisasi atau asinkron)
Non blocking: kontrol kembali ke proses segera setelah doa