Pertanyaan Variabel Kondisional vs Semaphore


Kapan sebaiknya menggunakan semaphore dan kapan harus menggunakan variabel kondisional (CondVar)?


75
2017-08-18 14:19


asal


Jawaban:


Kunci digunakan untuk pengecualian bersama. Ketika Anda ingin memastikan bahwa sepotong kode adalah atom, letakkan kunci di sekitarnya. Anda bisa secara teoritis menggunakan semaphore biner untuk melakukan ini, tapi itu kasus khusus.

Semaphores dan variabel kondisi yang dibangun di atas pengecualian bersama 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 sibuk menunggu (berulang berulang saat memeriksa kondisi) sambil menunggu sumber daya tersedia. Misalnya, jika Anda memiliki untaian (atau beberapa utas) yang tidak dapat terus berlanjut hingga antrian kosong, pendekatan menunggu yang sibuk adalah melakukan sesuatu seperti:

//pseudocode
while(!queue.empty())
{
   sleep(1);
}

Masalah dengan ini adalah bahwa Anda membuang-buang waktu prosesor dengan memiliki thread ini berulang kali memeriksa kondisi. Mengapa tidak memiliki variabel sinkronisasi yang dapat memberi isyarat untuk memberi tahu bahwa sumber daya tersedia?

//pseudocode
syncVar.lock.acquire();

while(!queue.empty())
{
   syncVar.wait();
}

//do stuff with queue

syncVar.lock.release();

Agaknya, Anda akan memiliki thread di tempat lain yang menarik hal-hal dari antrian. Ketika antrian kosong, ia bisa menelepon syncVar.signal() untuk membangun kembali utas acak yang sedang tidur syncVar.wait() (atau biasanya juga ada signalAll() atau broadcast() metode untuk membangun semua utas yang menunggu).

Saya biasanya menggunakan variabel sinkronisasi seperti ini ketika saya memiliki satu atau lebih untaian yang menunggu pada satu kondisi tertentu (misalnya untuk antrian kosong).

Semaphores dapat digunakan sama, tetapi saya pikir mereka lebih baik digunakan ketika Anda memiliki sumber daya bersama yang dapat tersedia dan tidak tersedia berdasarkan beberapa bilangan integer dari hal-hal yang tersedia. Semaphore bagus untuk situasi produsen / konsumen di mana produsen mengalokasikan sumber daya dan konsumen mengkonsumsinya.

Pikirkan tentang jika Anda memiliki mesin penjual minuman soda. Hanya ada satu mesin soda dan itu adalah sumber daya bersama. Anda memiliki satu thread yang merupakan vendor (produsen) yang bertanggung jawab untuk menjaga persediaan mesin dan N thread yang merupakan pembeli (konsumen) yang ingin mendapatkan soda dari mesin. Jumlah soda di mesin adalah nilai integer yang akan mendorong semaphore kami.

Setiap pembeli (konsumen) benang yang datang ke mesin soda memanggil semaphore down() metode untuk minum soda. Ini akan mengambil soda dari mesin dan mengurangi jumlah soda yang tersedia dengan 1. Jika ada soda tersedia, kode akan terus berjalan melewati down() pernyataan tanpa masalah. Jika tidak ada soda, benang akan tidur di sini menunggu untuk diberi tahu kapan soda tersedia lagi (bila ada lebih banyak soda di mesin).

Benang vendor (produsen) pada dasarnya akan menunggu mesin soda kosong. Vendor mendapat pemberitahuan ketika soda terakhir diambil dari mesin (dan satu atau lebih konsumen berpotensi menunggu untuk mengeluarkan soda). Vendor akan mengisi kembali mesin soda dengan semaphore up()metode, jumlah soda yang tersedia akan bertambah setiap kali dan dengan demikian benang konsumen yang menunggu akan diberitahu bahwa lebih banyak soda tersedia.

Itu wait() dan signal() metode dari variabel sinkronisasi cenderung disembunyikan di dalam down() dan up() operasi semaphore.

Tentu saja ada tumpang tindih antara dua pilihan itu. Ada banyak skenario di mana semaphore atau variabel kondisi (atau set variabel kondisi) bisa melayani tujuan Anda. Kedua semaphores dan variabel kondisi terkait dengan objek kunci yang mereka gunakan untuk mempertahankan eksklusi bersama, tetapi kemudian mereka menyediakan fungsionalitas tambahan di atas kunci untuk sinkronisasi eksekusi thread. Ini sebagian besar terserah Anda untuk mencari tahu mana yang paling masuk akal untuk situasi Anda.

Itu belum tentu deskripsi yang paling teknis, tapi itulah yang masuk akal di kepala saya.


156
2017-08-18 16:35



Mari mengungkapkan apa yang ada di balik kap mesin.

Variabel kondisional pada dasarnya adalah antrian menunggu, yang mendukung operasi pemblokiran-tunggu dan bangun, yaitu Anda dapat memasukkan utas ke antrean tunggu dan mengatur statusnya ke BLOK, dan mendapatkan utas dari situ dan mengatur statusnya menjadi SIAP.

Perhatikan bahwa untuk menggunakan variabel kondisional, dua elemen lain diperlukan:

  • suatu kondisi (biasanya diimplementasikan dengan memeriksa bendera atau counter)
  • sebuah mutex yang melindungi kondisi

Protokol kemudian menjadi,

  1. memperoleh mutex
  2. periksa kondisi
  3. blokir dan lepaskan mutex jika kondisi benar, yang lain lepaskan mutex

Semaphore pada dasarnya adalah counter + a mutex + antrian tunggu. Dan itu dapat digunakan seperti itu tanpa ketergantungan eksternal. Anda dapat menggunakannya sebagai mutex atau sebagai variabel kondisional.

Oleh karena itu, semaphore dapat diperlakukan sebagai struktur yang lebih canggih daripada variabel kondisional, sementara yang terakhir lebih ringan dan fleksibel.


24
2017-11-24 20:30



Semaphores dapat digunakan untuk menerapkan akses eksklusif ke variabel, namun mereka dimaksudkan untuk digunakan untuk sinkronisasi. Mutexes, di sisi lain, memiliki semantik yang secara ketat terkait dengan eksklusi mutual: hanya proses yang mengunci sumber daya yang dibolehkan untuk membukanya.

Sayangnya Anda tidak dapat menerapkan sinkronisasi dengan mutex, itulah sebabnya kami memiliki variabel kondisi. Perhatikan juga bahwa dengan variabel kondisi Anda dapat membuka semua thread tunggu dalam waktu yang sama dengan menggunakan unlocking broadcast. Ini tidak bisa dilakukan dengan semaphores.


13
2017-08-18 16:44



variabel semaphore dan kondisi sangat mirip dan digunakan sebagian besar untuk tujuan yang sama. Namun, ada perbedaan kecil yang bisa membuat satu lebih disukai. Misalnya, untuk menerapkan sinkronisasi penghalang Anda tidak akan dapat menggunakan semaphore. Tetapi variabel kondisi adalah ideal.

Sinkronisasi penghalang adalah ketika Anda ingin semua utas Anda menunggu hingga semua orang tiba di bagian tertentu dalam fungsi untaian. ini dapat diimplementasikan dengan memiliki variabel statis yang awalnya nilai total benang dikurangi oleh setiap thread ketika mencapai penghalang itu. ini berarti kita ingin setiap utas tidur sampai yang terakhir tiba. Semaphore akan melakukan yang sebaliknya! dengan semaphore, setiap thread akan terus berjalan dan thread terakhir (yang akan mengatur nilai semaphore ke 0) akan pergi tidur.

sebuah variabel kondisi di sisi lain, sangat ideal. ketika setiap thread sampai ke penghalang kami memeriksa apakah penghitung statis kami nol. jika tidak, kami mengatur utas untuk tidur dengan kondisi menunggu fungsi variabel. ketika thread terakhir tiba di penghalang, nilai counter akan dikurangi menjadi nol dan thread terakhir ini akan memanggil fungsi sinyal variabel kondisi yang akan membangun semua thread lainnya!


5
2017-12-22 03:43



Saya mengarsipkan variabel kondisi di bawah sinkronisasi monitor. Saya sering melihat semaphores dan monitor sebagai dua gaya sinkronisasi yang berbeda. Ada perbedaan antara keduanya dalam hal seberapa banyak data negara yang disimpan secara inheren dan bagaimana Anda ingin memodelkan kode - tetapi sebenarnya tidak ada masalah yang dapat diselesaikan oleh satu tetapi tidak yang lain.

Saya cenderung kode ke bentuk monitor; di sebagian besar bahasa saya bekerja di yang bermuara pada mutex, variabel kondisi, dan beberapa variabel status backing. Tapi semaphores akan melakukan pekerjaan itu juga.


1
2017-08-18 16:44