http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx
Para crear un semáforo, necesito proporcionar un recuento inicial y un recuento máximo. MSDN indica que un recuento inicial es:
El número inicial de solicitudes para el semáforo que se pueden otorgar al mismo tiempo.
Si bien establece que el recuento máximo es
El número máximo de solicitudes para el semáforo que se pueden otorgar al mismo tiempo.
Puedo entender que el recuento máximo es el número máximo de subprocesos que pueden acceder a un recurso al mismo tiempo. Pero, ¿de 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 podrá acceder al recurso. Si configuro el recuento inicial como 1 y el recuento máximo como 2, solo el subproceso del grupo de subprocesos puede acceder al recurso. Solo cuando configuro el recuento inicial y el recuento máximo como 2, 2 subprocesos pueden acceder al recurso al mismo tiempo. Entonces, ¿estoy realmente confundido acerca del significado 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
fuente
Respuestas:
Sí, cuando el número inicial se establece en 0, todos los subprocesos estarán esperando mientras incrementa la propiedad "CurrentCount". Puede hacerlo con Release () o Release (Int32).
Release (...) - incrementará el contador de semáforos
Espera (...) - lo disminuirá
No puede incrementar el contador (propiedad "CurrentCount") más que el conteo 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()
fuente
Un punto importante que puede ayudar aquí es que
Wait
disminuye el recuento de semáforos y loRelease
incrementa.initialCount
es el número de accesos a recursos que se permitirán inmediatamente. O, en otras palabras, es el número de veces queWait
se puede llamar sin bloquear inmediatamente después de crear una instancia del semáforo.maximumCount
es el recuento más alto que puede obtener el semáforo. Es el número de veces queRelease
se puede llamar sin lanzar una excepción asumiendo que elinitialCount
recuento es cero. SiinitialCount
se establece en el mismo valor quemaximumCount
entonces, llamarRelease
inmediatamente después de que se creó una instancia del semáforo arrojará una excepción.fuente
initialCount
parámetro.¿A cuántos subprocesos desea poder acceder a los recursos a la vez? Establezca su conteo inicial en ese número. Si ese número nunca va a aumentar durante la vida del programa, establezca su conteo máximo en ese número también. De esa manera, si tiene un error de programación en la forma en que libera el recurso, su programa se bloqueará y se lo informará.
(Hay dos constructores: uno que toma solo un valor inicial y otro que adicionalmente toma el recuento máximo. Use el que sea apropiado).
fuente
De esta manera, cuando el hilo actual crea el semáforo, podría reclamar algunos recursos desde el principio.
fuente
Si desea que ningún hilo acceda a su recurso durante algún tiempo, pasa el recuento inicial como 0 y cuando desee otorgar acceso a todos ellos 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 la documentación de MSDN: "Otro uso de ReleaseSemaphore es durante la inicialización de una aplicación. La aplicación puede crear un semáforo con una cuenta inicial de cero. Esto establece el estado del semáforo en no señalizado y bloquea todos los subprocesos para que no accedan al recurso protegido. Cuando la aplicación termina su inicialización, utiliza ReleaseSemaphore para aumentar el recuento a su valor máximo, para permitir el acceso normal al recurso protegido ".
fuente
Los semáforos se pueden utilizar para proteger un conjunto de recursos . Usamos grupos de recursos para reutilizar elementos que son costosos de crear , como conexiones de bases de datos.
Por tanto, el recuento inicial se refiere al número de recursos disponibles en el grupo al inicio de algún proceso. Cuando lea el
initialCount
código en, debería pensar en términos de cuánto esfuerzo inicial está poniendo en la creación de este grupo de recursos.Initial count
=Upfront cost
Como tal, dependiendo del perfil de uso de su aplicación, este valor puede tener un efecto dramático en el rendimiento de su aplicación. No es solo un número arbitrario.
Debe pensar detenidamente sobre lo que está creando, lo caro que es crearlos y cuántos necesita de inmediato. Literalmente, debería poder graficar el valor óptimo para este parámetro y probablemente debería pensar en hacerlo configurable para poder adaptar el rendimiento del proceso al momento en que se está ejecutando.
fuente
Como lo explica MSDN en la sección Comentarios:
Entonces, si el recuento inicial es 0 y el máximo es 2, es como si el hilo principal hubiera llamado a WaitOne dos veces, por lo que hemos alcanzado la capacidad (el recuento del semáforo es 0 ahora) y ningún hilo puede entrar en Semaphore. De manera similar, si el recuento inicial es 1 y el máximo es 2, WaitOnce se ha llamado una vez y solo puede ingresar un hilo antes de que alcancemos la capacidad nuevamente y así sucesivamente.
Si se usa 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.
fuente