c# - semáforo - significado de cada luz del semaforo
Semáforo: ¿para qué sirve el recuento inicial? (6)
http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx
Para crear un semáforo, necesito proporcionar un recuento inicial y recuento máximo. MSDN afirma que un conteo inicial es -
El número inicial de solicitudes de semáforo que se pueden otorgar simultáneamente.
Si bien establece que el recuento máximo es
El número máximo de solicitudes para el semáforo que se pueden otorgar simultáneamente.
Puedo entender que el recuento máximo es la cantidad máxima de subprocesos que pueden acceder a un recurso al mismo tiempo. Pero, ¿para qué sirve el recuento inicial?
Si creo un semáforo con un recuento inicial de 0 y un recuento máximo de 2, ninguno de mis subprocesos de subprocesos puede acceder al recurso. Si configuro el recuento inicial como 1 y el recuento máximo como 2, solo el subárbol de subprocesos puede acceder al recurso. Solo cuando establezco el recuento inicial y el recuento máximo como 2, 2 subprocesos pueden acceder al recurso al mismo tiempo. Entonces, ¿estoy realmente confundido sobre la importancia del recuento 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
Entonces, ¿estoy realmente confundido sobre la importancia del recuento inicial?
Un punto importante que puede ayudar aquí es que Wait
disminuye el recuento de semáforos y Release
incrementa.
initialCount
es la cantidad de acceso a recursos que se permitirá de forma inmediata. O, en otras palabras, es la cantidad de veces que se puede llamar a Wait
sin bloquear inmediatamente después de la creación de la instancia del semáforo.
maximumCount
es el recuento más alto que puede obtener el semáforo. Es la cantidad de veces que se puede initialCount
Release
sin lanzar una excepción, suponiendo que el conteo initialCount
fue cero. Si initialCount
se establece en el mismo valor que maximumCount
, la invocación de Release
inmediatamente después de la creación de la instancia del semáforo generará una excepción.
¿Cuántos hilos desea poder acceder al recurso a la vez? Establezca su conteo inicial a ese número. Si ese número nunca va a aumentar a lo largo de la vida del programa, establezca su recuento máximo en ese número también. De esta forma, si tiene un error de programación en la forma de liberar el recurso, su programa se bloqueará y le avisará.
(Hay dos constructores: uno que toma solo un valor inicial, y uno que adicionalmente toma el recuento máximo. Utilice el que sea apropiado).
Como MSDN lo explica en la sección Observaciones:
Si initialCount es menor que maximumCount, el efecto es el mismo que si el hilo actual hubiera llamado a WaitOne (maximumCount menos InitialCount) veces. Si no desea reservar ninguna entrada para el hilo que crea el semáforo, use el mismo número para maximumCount y initialCount.
Entonces, si el recuento inicial es 0 y el máximo es 2, es como si WaitOne hubiera sido llamado dos veces por el hilo principal, por lo que hemos alcanzado la capacidad (el recuento del semáforo es 0 ahora) y ningún hilo puede ingresar al semáforo. De manera similar, si el recuento inicial es 1 y el máximo es 2, se ha llamado a WaitOnce una vez y solo puede entrar un hilo antes de que alcancemos la capacidad nuevamente, y así sucesivamente.
Si se utiliza 0 para el recuento inicial siempre podemos llamar a Release (2) para aumentar el recuento de semáforos al máximo para permitir que el número máximo de subprocesos adquiera recursos.
De esta manera, cuando el hilo actual crea el semáforo podría reclamar algunos recursos desde el inicio.
Sí, cuando el número inicial se establece en 0, todos los hilos estarán esperando mientras usted incrementa la propiedad "CurrentCount". Puede hacerlo con Release () o Release (Int32).
Release (...) - incrementará el contador de semáforos
Espera (...) - lo reducirá
No puede incrementar el contador (propiedad "CurrentCount") mayor que el recuento máximo que estableció en la inicialización.
Por ejemplo:
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()
Si desea que ningún subproceso tenga acceso a su recurso durante un tiempo, pasa el recuento inicial como 0 y cuando desea otorgar acceso a todos justo después de crear el semáforo, pasa el valor del recuento inicial igual al recuento máximo . Por ejemplo:
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
Como se cita en MSDN Documentation: "Otro uso de ReleaseSemaphore es durante la inicialización de una aplicación. La aplicación puede crear un semáforo con un recuento inicial de cero. Esto establece el estado del semáforo en no señalado y bloquea todos los subprocesos para acceder al recurso protegido. finaliza su inicialización, usa ReleaseSemaphore para aumentar el recuento a su valor máximo, para permitir el acceso normal al recurso protegido ".