Semaphore dan SemaphoreSlim

Kelas System.Threading.Semaphore mewakili semaphore yang dinamai (systemwide) atau lokal. Ini adalah pembungkus tipis di sekitar objek Win32 semaphore. Win32 semaphores menghitung semaphores yang mengontrol akses ke kumpulan sumber daya.

Kelas SemaphoreSlim ini mewakili semaphore yang ringan dan cepat, yang dapat digunakan untuk melakukan penundaan dalam satu proses ketika waktu tunggu diperkirakan singkat. Selama fase spin-wait, CPU secara aktif beroperasi—tidak dalam keadaan diam. Seberapa pendek "pendek" harus tergantung pada sifat penantian: jika utas bersaing untuk sumber daya CPU, utas yang berputar memakan waktu pemrosesan CPU, sehingga penantian harus sangat singkat, diukur dalam mikrodetik. Jika waktu tunggu adalah untuk sumber daya yang tidak terikat CPU (seperti I/O), overhead spin-wait tidak terlalu menjadi masalah, dan waktu tunggu yang dapat diterima bisa agak lebih lama, diukur dalam milidetik. Ketika waktu tunggu tidak dapat diprediksi atau diperkirakan signifikan, gunakan System.Threading.Semaphore sebagai gantinya, yang tidak berputar. SemaphoreSlim bergantung sebanyak mungkin pada primitif sinkronisasi yang disediakan oleh lingkungan pemrosesan bahasa umum (CLR). Namun, ini juga menyediakan handle tunggu berbasis kernel yang diinisialisasi secara malas seperlunya untuk mendukung menunggu beberapa semaphore. SemaphoreSlim juga mendukung penggunaan token pembatalan, tetapi tidak mendukung semaphore bernama atau penggunaan handle tunggu untuk sinkronisasi.

Mengelola sumber daya terbatas

Utas memasuki semaphore dengan memanggil metode yang berbeda tergantung pada jenis semaphore. Untuk sebuah objek System.Threading.Semaphore, memanggil metode WaitOne (diwarisi dari WaitHandle). Untuk objek SemaphoreSlim, panggil metode SemaphoreSlim.Wait atau SemaphoreSlim.WaitAsync. Ketika panggilan selesai, hitungan pada semaphore berkurang. Ketika sebuah utas meminta entri dan jumlah entri nol, utas tersebut terblokir. Saat utas melepaskan semaphore dengan memanggil metode Semaphore.Release atau SemaphoreSlim.Release, utas yang terblokir dapat masuk. Tidak ada urutan yang dijamin—seperti first-in, first-out (FIFO) atau last-in, first-out (LIFO)—menentukan utas yang terblokir untuk memasuki semaphore selanjutnya.

Utas dapat memasuki semaphore beberapa kali dengan memanggil metode objek System.Threading.SemaphoreWaitOne atau metode objek SemaphoreSlimWait berulang kali. Untuk melepaskan semaphore, panggil metode Semaphore.Release() atau SemaphoreSlim.Release() sejumlah kali ketika utas memasukinya. Atau, gunakan Semaphore.Release(Int32) atau SemaphoreSlim.Release(Int32) overload dan tentukan jumlah entri yang akan dilepaskan.

Semafor dan identitas utas

Dua jenis semaphore tidak menegakkan identitas utas pada panggilan ke metode WaitOne, Wait, Release, dan SemaphoreSlim.Release. Misalnya, skenario penggunaan umum untuk semaphore melibatkan utas produsen dan utas konsumen, dengan satu utas bertugas selalu menambah jumlah semaphore dan yang lain bertugas untuk selalu mengurangkannya.

Pastikan bahwa utas tidak terlalu sering melepaskan semaphore. Misalnya, anggaplah semaphore memiliki batas maksimum dua, dan baik utas A maupun utas B memasuki semaphore tersebut. Jika kesalahan pemrograman di utas B menyebabkannya memanggil Release dua kali, kedua panggilan berhasil. Hitungan pada semaphore penuh, dan ketika utas A akhirnya memanggil Release, sebuah SemaphoreFullException dilemparkan.

Semaphore bernama

Sistem operasi Windows memungkinkan semafor memiliki nama. Semaphore bernama bersifat seluruh sistem—setelah diciptakan, itu terlihat oleh semua utas di semua proses. Oleh karena itu, semafor bernama dapat menyinkronkan aktivitas dari proses maupun utas.

Buat Semaphore objek yang mewakili semaphore sistem bernama dengan menggunakan salah satu konstruktor yang menentukan nama.

Penting

Karena semaphores bernama bersifat sistem luas, dimungkinkan adanya beberapa Semaphore objek yang mewakili semaphore bernama yang sama. Setiap kali Anda memanggil konstruktor atau Semaphore.OpenExisting metode , objek baru Semaphore dibuat. Menentukan nama yang sama berulang kali membuat beberapa objek yang mewakili semaphore bernama yang sama.

Berhati-hatilah ketika Anda menggunakan semafor yang diberi nama. Karena luas sistem, proses lain yang menggunakan nama yang sama dapat memasukkan semaphore Anda secara tak terduga. Kode berbahaya yang dijalankan pada komputer yang sama dapat menggunakan ini sebagai dasar serangan penolakan layanan.

Gunakan keamanan kontrol akses untuk melindungi objek Semaphore yang mewakili semaphore dengan nama tertentu, sebaiknya dengan menggunakan konstruktor yang menentukan objek System.Security.AccessControl.SemaphoreSecurity. Anda juga dapat menerapkan keamanan kontrol akses menggunakan metode Semaphore.SetAccessControl, tetapi ini meninggalkan celah kerentanan antara waktu semaphore dibuat dan waktu saat terlindungi. Melindungi semaphores dengan kontrol akses keamanan membantu mencegah serangan yang berniat jahat, tetapi tidak menyelesaikan masalah tabrakan nama yang tidak disengaja.

Lihat juga