http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx
Para criar um semáforo, preciso fornecer uma contagem inicial e uma contagem máxima. MSDN afirma que uma contagem inicial é -
O número inicial de solicitações do semáforo que podem ser concedidas simultaneamente.
Embora afirme que a contagem máxima é
O número máximo de solicitações para o semáforo que podem ser concedidas simultaneamente.
Posso entender que a contagem máxima é o número máximo de threads que podem acessar um recurso simultaneamente. Mas, qual é a utilidade da contagem inicial?
Se eu criar um semáforo com uma contagem inicial de 0 e uma contagem máxima de 2, nenhum dos meus threads de threadpool será capaz de acessar o recurso. Se eu definir a contagem inicial como 1 e a contagem máxima como 2, apenas o thread do pool de threads poderá acessar o recurso. Somente quando eu defino a contagem inicial e a contagem máxima como 2, 2 threads podem acessar o recurso simultaneamente. Então, estou realmente confuso sobre o significado da contagem inicial?
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
fonte
Um ponto importante que pode ajudar aqui é que
Wait
diminui a contagem do semáforo e aRelease
incrementa.initialCount
é o número de acessos a recursos que serão permitidos imediatamente. Ou, em outras palavras, é o número de vezes queWait
pode ser chamado sem bloquear imediatamente após o semáforo ser instanciado.maximumCount
é a contagem mais alta que o semáforo pode obter. É o número de vezes queRelease
pode ser chamado sem lançar uma exceção, supondo que ainitialCount
contagem seja zero. SeinitialCount
estiver definido com o mesmo valor quemaximumCount
então, chamarRelease
imediatamente após o semáforo ser instanciado lançará uma exceção.fonte
initialCount
parâmetro.Quantos threads você deseja poder acessar o recurso de uma vez? Defina sua contagem inicial para esse número. Se esse número nunca vai aumentar ao longo da vida do programa, defina sua contagem máxima para esse número também. Dessa forma, se você tiver um erro de programação em como libera o recurso, seu programa irá travar e informá-lo.
(Existem dois construtores: um que leva apenas um valor inicial e outro que adicionalmente leva a contagem máxima. Use o que for apropriado.)
fonte
Se você deseja que nenhuma thread acesse seu recurso por algum tempo, você passa a contagem inicial como 0 e quando deseja conceder acesso a todos eles logo após a criação do semáforo, você passa o valor da contagem inicial igual à contagem máxima . Por exemplo:
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
Conforme citado na documentação do MSDN- "Outro uso de ReleaseSemaphore é durante a inicialização de um aplicativo. O aplicativo pode criar um semáforo com uma contagem inicial de zero. Isso define o estado do semáforo como sem sinal e bloqueia todos os threads de acesso ao recurso protegido. Quando o aplicativo terminar sua inicialização, ele usa ReleaseSemaphore para aumentar a contagem ao seu valor máximo, para permitir o acesso normal ao recurso protegido. "
fonte
Dessa forma, quando o thread atual cria o semáforo, ele pode reivindicar alguns recursos desde o início.
fonte
Os semáforos podem ser usados para proteger um conjunto de recursos . Usamos pools de recursos para reutilizar coisas que são caras de criar - como conexões de banco de dados.
Portanto, a contagem inicial se refere ao número de recursos disponíveis no pool no início de algum processo. Ao ler o
initialCount
código, você deve estar pensando em quanto esforço inicial está investindo na criação desse pool de recursos.Initial count
=Upfront cost
Como tal, dependendo do perfil de uso de seu aplicativo, este valor pode ter um efeito dramático no desempenho de seu aplicativo. Não é apenas um número arbitrário.
Você deve pensar cuidadosamente sobre o que está criando, como é caro criar e quantos você precisa imediatamente. Você deve literalmente ser capaz de representar graficamente o valor ideal para este parâmetro e provavelmente deve pensar em torná-lo configurável para que possa adaptar o desempenho do processo ao momento em que está sendo executado.
fonte
Como o MSDN explica na seção Comentários:
Portanto, se a contagem inicial for 0 e o máximo for 2, é como se WaitOne tivesse sido chamado duas vezes pelo encadeamento principal, de modo que atingimos a capacidade (a contagem do semáforo é 0 agora) e nenhum encadeamento pode entrar no semáforo. Da mesma forma, se a contagem inicial for 1 e max for 2, WaitOnce foi chamado uma vez e apenas um thread pode entrar antes de atingirmos a capacidade novamente e assim por diante.
Se 0 for usado para a contagem inicial, sempre podemos chamar Release (2) para aumentar a contagem do semáforo para o máximo para permitir o número máximo de threads para adquirir o recurso.
fonte