http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx
Aby utworzyć semafor, muszę podać liczbę początkową i maksymalną. MSDN stwierdza, że początkowa liczba to -
Początkowa liczba żądań semafora, które mogą być przyznane jednocześnie.
Chociaż stwierdza, że maksymalna liczba to
Maksymalna liczba żądań semafora, które mogą być przyznane jednocześnie.
Rozumiem, że maksymalna liczba to maksymalna liczba wątków, które mogą jednocześnie uzyskać dostęp do zasobu. Ale jaki jest pożytek z liczenia początkowego?
Jeśli utworzę semafor z początkową liczbą 0 i maksymalną liczbą 2, żaden z moich wątków wątków nie będzie mógł uzyskać dostępu do zasobu. Jeśli ustawię początkową liczbę na 1 i maksymalną liczbę na 2, tylko wątek puli wątków będzie miał dostęp do zasobu. To jest tylko wtedy, gdy ustawię zarówno początkową liczbę, jak i maksymalną liczbę na 2, 2 wątki mogą jednocześnie uzyskać dostęp do zasobu. Więc jestem naprawdę zdezorientowany co do znaczenia początkowej liczby?
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
źródło
Odpowiedzi:
Tak, gdy początkowa liczba jest ustawiona na 0 - wszystkie wątki będą czekać podczas zwiększania właściwości „CurrentCount”. Możesz to zrobić za pomocą Release () lub Release (Int32).
Release (...) - zwiększy licznik semaforów
Czekaj (...) - zmniejszy to
Nie można zwiększyć licznika (właściwość „CurrentCount”) powyżej maksymalnej liczby ustawionej podczas inicjalizacji.
Na przykład:
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()
źródło
Jedna ważna kwestia, która może tutaj pomóc, jest taka
Wait
zmniejszenie liczby semaforów iRelease
zwiększenie jej.initialCount
to liczba dostępów do zasobów, które będą natychmiast dozwolone. Innymi słowy, jest to liczba wywołań, któreWait
można wywołać bez blokowania bezpośrednio po utworzeniu wystąpienia semafora.maximumCount
jest największą liczbą, jaką może uzyskać semafor. Jest to liczba wywołań, któreRelease
można wywołać bez zgłaszania wyjątku, zakładając, żeinitialCount
liczba wynosi zero. JeśliinitialCount
jest ustawiona na taką samą wartość, jakmaximumCount
wtedy, wywołanieRelease
natychmiast po utworzeniu wystąpienia semafora spowoduje zgłoszenie wyjątku.źródło
initialCount
parametru.Ile wątków chcesz mieć jednocześnie dostęp do zasobów? Ustaw początkową liczbę na tę liczbę. Jeśli ta liczba nigdy nie wzrośnie przez cały czas trwania programu, ustaw maksymalną liczbę również na tę liczbę. W ten sposób, jeśli wystąpi błąd programowania dotyczący sposobu zwalniania zasobu, program ulegnie awarii i poinformuje Cię o tym.
(Istnieją dwa konstruktory: jeden, który przyjmuje tylko wartość początkową, i drugi, który dodatkowo przyjmuje maksymalną liczbę. Użyj tego, który jest odpowiedni).
źródło
W ten sposób, gdy bieżący wątek tworzy semafor, może zażądać pewnych zasobów od początku.
źródło
Jeśli chcesz, aby żaden wątek nie miał dostępu do twojego zasobu przez jakiś czas, przekazujesz początkową liczbę jako 0, a gdy chcesz udzielić dostępu wszystkim z nich zaraz po utworzeniu semafora, przekazujesz wartość początkowego licznika równą maksymalnej liczbie . Na przykład:
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
Jak podano w dokumentacji MSDN - „Innym zastosowaniem ReleaseSemaphore jest inicjalizacja aplikacji. Aplikacja może utworzyć semafor z początkową liczbą zerową. To ustawia stan semafora na niesygnalizowany i blokuje dostęp wszystkich wątków do chronionego zasobu. Gdy aplikacja kończy inicjalizację, używa ReleaseSemaphore w celu zwiększenia liczby do wartości maksymalnej, aby umożliwić normalny dostęp do chronionego zasobu. "
źródło
Semafory mogą służyć do ochrony puli zasobów . Używamy pul zasobów do ponownego wykorzystania rzeczy, których tworzenie jest drogie - takich jak połączenia z bazami danych.
Zatem początkowa liczba odnosi się do liczby dostępnych zasobów w puli na początku jakiegoś procesu. Czytając
initialCount
kod, powinieneś pomyśleć o tym, ile wysiłku wkładasz z góry w tworzenie tej puli zasobów.Initial count
=Upfront cost
W związku z tym, w zależności od profilu użytkowania aplikacji, wartość ta może mieć dramatyczny wpływ na wydajność aplikacji. To nie jest dowolna liczba.
Powinieneś dokładnie przemyśleć, co tworzysz, jak drogie są one w tworzeniu i ile potrzebujesz od razu. Powinieneś być w stanie dosłownie być w stanie wykreślić optymalną wartość tego parametru i prawdopodobnie powinieneś pomyśleć o skonfigurowaniu go, abyś mógł dostosować wydajność procesu do czasu, w którym jest wykonywany.
źródło
Jak wyjaśnia MSDN w sekcji Uwagi:
Więc jeśli początkowa liczba to 0, a max to 2, to tak, jakby WaitOne został wywołany dwukrotnie przez główny wątek, więc osiągnęliśmy pojemność (liczba semaforów wynosi teraz 0) i żaden wątek nie może wejść do Semafora. Podobnie, jeśli początkowa liczba to 1, a maksymalna to 2, WaitOnce został wywołany raz i tylko jeden wątek może wejść, zanim ponownie osiągniemy pojemność i tak dalej.
Jeśli do zliczania początkowego użyto 0, zawsze możemy wywołać Release (2), aby zwiększyć liczbę semaforów do maks., Aby umożliwić maksymalną liczbę wątków w celu uzyskania zasobu.
źródło