Semaphore - Apa gunanya hitungan awal?

91

http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx

Untuk membuat semaphore, saya perlu memberikan hitungan awal dan hitungan maksimal. MSDN menyatakan bahwa hitungan awal adalah -

Jumlah awal permintaan untuk semaphore yang dapat diberikan secara bersamaan.

Sementara itu menyatakan bahwa jumlah maksimumnya adalah

Jumlah maksimum permintaan untuk semaphore yang dapat diberikan secara bersamaan.

Saya dapat memahami bahwa jumlah maksimum adalah jumlah maksimum utas yang dapat mengakses sumber daya secara bersamaan. Tapi, apa gunanya hitungan awal?

Jika saya membuat semaphore dengan jumlah awal 0 dan jumlah maksimum 2, tidak ada utas threadpool saya yang dapat mengakses sumber daya. Jika saya menetapkan jumlah awal sebagai 1 dan jumlah maksimum sebagai 2 maka hanya thread pool thread yang dapat mengakses sumber daya. Hanya ketika saya menetapkan jumlah awal dan jumlah maksimum sebagai 2, 2 utas dapat mengakses sumber daya secara bersamaan. Jadi, saya benar-benar bingung tentang pentingnya hitungan awal?

SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0, 2); //all threadpool threads wait
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 2);//only one thread has access to the resource at a time
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2, 2);//two threadpool threads can access the resource concurrently
Bak pasir
sumber
7
Kenapa Anda tidak pernah menerima jawaban SVGreg?
Yohanes

Jawaban:

79

Ya, ketika nomor awal disetel ke 0 - semua utas akan menunggu saat Anda menaikkan properti "JumlahSurya". Anda dapat melakukannya dengan Release () atau Release (Int32).

Rilis (...) - akan menaikkan penghitung semaphore

Tunggu (...) - akan mengurangi itu

Anda tidak dapat menaikkan penghitung (properti "CurrentCount") lebih besar dari jumlah maksimum yang Anda tetapkan dalam inisialisasi.

Sebagai contoh:

SemaphoreSlim^ s = gcnew SemaphoreSlim(0,2); //s->CurrentCount = 0
s->Release(2); //s->CurrentCount = 2
...

s->Wait(); //Ok. s->CurrentCount = 1
...

s->Wait(); //Ok. s->CurrentCount = 0
...

s->Wait(); //Will be blocked until any of the threads calls Release()
SVGreg
sumber
1
Kode Anda akan lebih baik disajikan dalam jawaban daripada sebagai komentar.
ChrisF
14
LOL mungkin ini adalah kelima kalinya saya mencapai jawaban yang sama ini karena dokumentasi konstruktor selalu membingungkan saya tentang nilai mana yang harus ditetapkan. Cheers
BlueStrat
70

Jadi, saya benar-benar bingung tentang pentingnya hitungan awal?

Satu hal penting yang dapat membantu di sini adalah bahwa Waitmengurangi jumlah semaphore dan Releasemenambahkannya.

initialCountadalah jumlah akses sumber daya yang akan segera diizinkan. Atau, dengan kata lain, itu adalah berapa kali Waitdapat dipanggil tanpa pemblokiran segera setelah semaphore dibuat.

maximumCountadalah jumlah tertinggi yang bisa diperoleh semaphore. Ini adalah berapa kali Releasedapat dipanggil tanpa mengeluarkan pengecualian dengan asumsi initialCounthitungan nol. Jika initialCountdisetel ke nilai yang sama seperti maximumCountkemudian memanggil Releasesegera setelah semaphore dibuat akan memunculkan pengecualian.

Brian Gideon
sumber
20
Ini sangat membantu! Saya telah memikirkan Semaphores secara mundur, seperti pada initialCount adalah jumlah sumber daya awal yang DIBLOKIR, bukan jumlah sumber daya yang tersedia dengan segera. Terima kasih.
Philip Tenn
5
@PhilipTenn, saya setuju - dokumentasinya tidak jelas tentang hal ini
BlueStrat
Saya setuju, mereka harus mengubah nama variabel itu atau memperbarui dokumen
IronHide
@ Sandbox Anda harus menerima jawaban ini IMO, karena ini benar-benar menjelaskan arti initialCountparameter.
Michał Turczyn tanggal
8

Berapa banyak utas yang Anda inginkan untuk dapat mengakses sumber daya sekaligus? Setel hitungan awal Anda ke angka itu. Jika angka itu tidak akan pernah meningkat sepanjang masa program, setel jumlah maksimal Anda ke angka itu juga. Dengan begitu, jika Anda mengalami kesalahan pemrograman dalam cara melepaskan sumber daya, program Anda akan macet dan memberi tahu Anda.

(Ada dua konstruktor: satu yang hanya mengambil nilai awal, dan yang satu lagi mengambil jumlah maksimal. Gunakan mana saja yang sesuai.)

Karmastan
sumber
1

Dengan cara ini ketika utas saat ini membuat semafor, ia dapat mengklaim beberapa sumber daya dari awal.

Erno
sumber
Jadi, maksud Anda ketika saya ingin dua utas pekerja mengakses sumber daya, saya harus mengubah jumlah awal?
Sandbox
Tidak. Utas saat ini yang mengklaim sebuah hitungan. Jika Anda tidak ingin thread saat ini mengklaim akses pass 0 atau menggunakan kelebihan beban dengan satu parameter.
Erno
1

Jika Anda ingin tidak ada utas yang mengakses sumber daya Anda untuk beberapa waktu, Anda meneruskan penghitungan awal sebagai 0 dan ketika Anda ingin memberikan akses ke semuanya tepat setelah membuat semaphore, Anda meneruskan nilai hitungan awal yang sama dengan jumlah maksimum . Sebagai contoh:

hSemaphore = CreateSemaphoreA(NULL, 0, MAX_COUNT, NULL) ;

//Do something here
//No threads can access your resource

ReleaseSemaphore(hSemaphore, MAX_COUNT, 0) ;

//All threads can access the resource now

Seperti dikutip dalam Dokumentasi MSDN- "Penggunaan lain dari ReleaseSemaphore adalah selama inisialisasi aplikasi. Aplikasi dapat membuat semaphore dengan hitungan awal nol. Ini menyetel status semaphore ke non-sinyal dan memblokir semua utas mengakses sumber daya yang dilindungi. Saat aplikasi menyelesaikan inisialisasinya, ia menggunakan ReleaseSemaphore untuk meningkatkan hitungan ke nilai maksimumnya, untuk mengizinkan akses normal ke sumber daya yang dilindungi. "

Abhineet
sumber
Maaf, saya memberi Anda contoh dalam C ++ meskipun dapat menghilangkan keraguan.
Abhineet
0

Semaphore dapat digunakan untuk melindungi kumpulan sumber daya . Kami menggunakan kumpulan sumber daya untuk menggunakan kembali hal-hal yang mahal untuk dibuat - seperti koneksi database.

Jadi penghitungan awal mengacu pada jumlah sumber daya yang tersedia di kumpulan pada awal beberapa proses. Ketika Anda membaca initialCountkode in, Anda harus berpikir tentang seberapa banyak upaya di muka yang Anda lakukan untuk membuat kumpulan sumber daya ini.

Saya benar-benar bingung tentang pentingnya hitungan awal?

Initial count = Upfront cost

Karenanya, bergantung pada profil penggunaan aplikasi Anda, nilai ini dapat memberikan efek dramatis pada kinerja aplikasi Anda. Ini bukan hanya angka sembarangan.

Anda harus memikirkan dengan hati-hati tentang apa yang Anda buat, seberapa mahal harganya dan berapa banyak yang Anda butuhkan segera. Anda harus benar-benar dapat membuat grafik nilai optimal untuk parameter ini dan kemungkinan besar harus berpikir untuk membuatnya dapat dikonfigurasi sehingga Anda dapat menyesuaikan kinerja proses dengan waktu saat itu dijalankan.

risme
sumber
-1

Seperti yang dijelaskan MSDN di bawah bagian Keterangan:

Jika initialCount kurang dari maximumCount, efeknya sama seperti jika utas saat ini memanggil WaitOne (maximumCount minus initialCount) kali. Jika Anda tidak ingin menyimpan entri apa pun untuk utas yang membuat semaphore, gunakan nomor yang sama untuk maximumCount dan initialCount.

Jadi Jika hitungan awal 0 dan maks 2, maka WaitOne seolah-olah telah dipanggil dua kali oleh utas utama sehingga kami telah mencapai kapasitas (jumlah semaphore 0 sekarang) dan tidak ada utas yang dapat masuk ke Semaphore. Demikian pula Jika hitungan awal adalah 1 dan maks adalah 2 WaitOnce telah dipanggil sekali dan hanya satu utas yang dapat masuk sebelum kami mencapai kapasitas lagi dan seterusnya.

Jika 0 digunakan untuk penghitungan awal, kami selalu dapat memanggil Rilis (2) untuk meningkatkan jumlah semaphore ke maksimum untuk memungkinkan jumlah maksimum utas memperoleh sumber daya.

Irfan
sumber