Kapan seseorang harus menggunakan semaphore dan kapan harus menggunakan variabel kondisional (CondVar)?
110
Kapan seseorang harus menggunakan semaphore dan kapan harus menggunakan variabel kondisional (CondVar)?
Jawaban:
Kunci digunakan untuk saling mengesampingkan. Jika Anda ingin memastikan bahwa sepotong kode adalah atom, letakkan kunci di sekitarnya. Anda secara teoritis dapat menggunakan semafor biner untuk melakukan ini, tetapi itu kasus khusus.
Variabel semaphore dan kondisi dibangun di atas pengecualian timbal balik yang disediakan oleh kunci dan digunakan untuk menyediakan akses yang disinkronkan ke sumber daya bersama. Mereka dapat digunakan untuk tujuan serupa.
Variabel kondisi umumnya digunakan untuk menghindari menunggu sibuk (mengulang berulang kali saat memeriksa kondisi) sambil menunggu sumber daya tersedia. Misalnya, jika Anda memiliki utas (atau beberapa utas) yang tidak dapat melanjutkan seterusnya sampai antrian kosong, pendekatan menunggu sibuk akan hanya melakukan sesuatu seperti:
Masalahnya adalah Anda membuang-buang waktu prosesor dengan meminta utas ini berulang kali memeriksa kondisinya. Mengapa tidak memiliki variabel sinkronisasi yang dapat diberi isyarat untuk memberi tahu thread bahwa sumber daya tersedia?
Agaknya, Anda akan memiliki utas di tempat lain yang menarik hal-hal keluar dari antrean. Saat antrean kosong, antrean dapat memanggil
syncVar.signal()
untuk mengaktifkan utas acak yang tertidursyncVar.wait()
(atau biasanya juga ada metodesignalAll()
ataubroadcast()
untuk mengaktifkan semua utas yang menunggu).Saya biasanya menggunakan variabel sinkronisasi seperti ini ketika saya memiliki satu atau lebih utas yang menunggu pada satu kondisi tertentu (misalnya agar antrian kosong).
Semaphore dapat digunakan dengan cara yang sama, tetapi saya pikir mereka lebih baik digunakan ketika Anda memiliki sumber daya bersama yang dapat tersedia dan tidak tersedia berdasarkan beberapa bilangan bulat dari hal-hal yang tersedia. Semaphore baik untuk situasi produsen / konsumen di mana produsen mengalokasikan sumber daya dan konsumen mengkonsumsinya.
Pikirkan apakah Anda memiliki mesin penjual soda. Hanya ada satu mesin soda dan itu adalah sumber daya bersama. Anda memiliki satu utas yang merupakan vendor (produsen) yang bertanggung jawab untuk menjaga stok mesin dan utas N yang merupakan pembeli (konsumen) yang ingin mengeluarkan soda dari mesin. Jumlah soda di mesin adalah nilai integer yang akan menggerakkan semaphore kita.
Setiap pembeli (konsumen) benang yang datang ke mesin soda memanggil
down()
metode semaphore untuk mengambil soda. Ini akan mengambil soda dari mesin dan mengurangi jumlah soda yang tersedia menjadi 1. Jika ada soda yang tersedia, kode akan terus berjalan melewatidown()
pernyataan tanpa masalah. Jika tidak ada soda yang tersedia, utas akan tidur di sini menunggu untuk diberi tahu kapan soda tersedia lagi (ketika ada lebih banyak soda di mesin).Benang vendor (produsen) pada dasarnya akan menunggu mesin soda kosong. Penjual diberi tahu saat soda terakhir diambil dari mesin (dan satu atau lebih konsumen berpotensi menunggu untuk mengeluarkan soda). Vendor akan mengisi kembali mesin soda dengan
up()
metode semaphore , jumlah soda yang tersedia akan bertambah setiap kali dan dengan demikian benang konsumen yang menunggu akan diberi tahu bahwa lebih banyak soda tersedia.Metode
wait()
dansignal()
dari variabel sinkronisasi cenderung disembunyikan di dalam operasidown()
danup()
semaphore.Pastinya ada tumpang tindih antara kedua pilihan tersebut. Ada banyak skenario di mana semafor atau variabel kondisi (atau kumpulan variabel kondisi) dapat memenuhi tujuan Anda. Variabel semaphore dan condition dikaitkan dengan objek kunci yang mereka gunakan untuk mempertahankan pengecualian timbal balik, tetapi kemudian keduanya menyediakan fungsionalitas tambahan di atas kunci untuk menyinkronkan eksekusi thread. Terserah Anda untuk mencari tahu mana yang paling masuk akal untuk situasi Anda.
Itu belum tentu merupakan deskripsi yang paling teknis, tapi itulah yang masuk akal di kepala saya.
sumber
Mari kita ungkapkan apa yang ada di balik tenda.
Variabel bersyarat pada dasarnya adalah antrian tunggu , yang mendukung operasi pemblokiran-tunggu dan bangun, yaitu Anda dapat meletakkan utas ke antrian tunggu dan menyetel statusnya ke BLOKIR, dan mengeluarkan utas darinya dan menyetel statusnya ke SIAP.
Perhatikan bahwa untuk menggunakan variabel bersyarat, dibutuhkan dua elemen lain:
Protokol kemudian menjadi,
Semaphore pada dasarnya adalah penghitung + mutex + antrian tunggu. Dan itu dapat digunakan apa adanya tanpa ketergantungan eksternal. Anda dapat menggunakannya sebagai mutex atau sebagai variabel bersyarat.
Oleh karena itu, semaphore dapat diperlakukan sebagai struktur yang lebih canggih daripada variabel bersyarat, sedangkan variabel bersyarat lebih ringan dan fleksibel.
sumber
Semaphore dapat digunakan untuk mengimplementasikan akses eksklusif ke variabel, namun mereka dimaksudkan untuk digunakan untuk sinkronisasi. Mutex, di sisi lain, memiliki semantik yang sangat terkait dengan pengecualian timbal balik: hanya proses yang mengunci sumber daya yang diizinkan untuk membukanya.
Sayangnya Anda tidak dapat mengimplementasikan sinkronisasi dengan mutex, itulah mengapa kami memiliki variabel kondisi. Juga perhatikan bahwa dengan variabel kondisi Anda dapat membuka kunci semua utas menunggu dalam sekejap dengan menggunakan pembukaan kunci siaran. Ini tidak dapat dilakukan dengan semaphore.
sumber
variabel semaphore dan condition sangat mirip dan sebagian besar digunakan untuk tujuan yang sama. Namun, ada perbedaan kecil yang membuat seseorang lebih disukai. Misalnya, untuk mengimplementasikan sinkronisasi penghalang, Anda tidak akan dapat menggunakan semaphore. Tetapi variabel kondisi sangat ideal.
Sinkronisasi penghalang adalah saat Anda ingin semua utas menunggu hingga semua orang tiba di bagian tertentu dalam fungsi utas. ini dapat diterapkan dengan memiliki variabel statis yang awalnya nilai total utas dikurangi oleh setiap utas ketika mencapai penghalang itu. ini berarti kita ingin setiap utas tidur sampai yang terakhir tiba. Semaphore akan melakukan sebaliknya! dengan semaphore, setiap utas akan terus berjalan dan utas terakhir (yang akan menyetel nilai semafor ke 0) akan tidur.
variabel kondisi di sisi lain, adalah ideal. ketika setiap utas mencapai penghalang, kami memeriksa apakah penghitung statis kami nol. jika tidak, kita menyetel utas ke tidur dengan fungsi tunggu variabel kondisi. ketika utas terakhir tiba di penghalang, nilai penghitung akan dikurangi menjadi nol dan utas terakhir ini akan memanggil fungsi sinyal variabel kondisi yang akan membangunkan semua utas lainnya!
sumber
Saya mengajukan variabel kondisi di bawah sinkronisasi monitor. Saya biasanya melihat semaphores dan monitor sebagai dua gaya sinkronisasi yang berbeda. Ada perbedaan antara keduanya dalam hal seberapa banyak data status disimpan secara inheren dan bagaimana Anda ingin membuat kode model - tetapi sebenarnya tidak ada masalah yang dapat diselesaikan oleh satu tetapi tidak yang lain.
Saya cenderung membuat kode ke bentuk monitor; dalam sebagian besar bahasa yang saya gunakan, itu turun ke mutex, variabel kondisi, dan beberapa variabel status pendukung. Tapi semaphores akan melakukan pekerjaan itu juga.
sumber
The
mutex
danconditional variables
diwarisi darisemaphore
.mutex
,semaphore
menggunakan dua status: 0, 1condition variables
yangsemaphore
menggunakan counter.Mereka seperti gula sintaksis
sumber