Objetos de semáforo

Un objeto de semáforo es un objeto de sincronización que mantiene un recuento entre cero y un valor máximo especificado. El recuento se disminuye cada vez que un subproceso completa una espera para el objeto de semáforo e incrementa cada vez que un subproceso libera el semáforo. Cuando el recuento alcanza cero, no más subprocesos pueden esperar correctamente a que se señale el estado del objeto de semáforo. El estado de un semáforo se establece como señalizado cuando su recuento es mayor que cero y como no señalizado cuando su recuento es cero.

El objeto de semáforo es útil para controlar un recurso compartido que puede admitir un número limitado de usuarios. Actúa como una puerta que limita el número de subprocesos que comparten el recurso a un número máximo especificado. Por ejemplo, una aplicación podría colocar un límite en el número de ventanas que crea. Usa un semáforo con un recuento máximo igual al límite de ventanas, disminuyendo el recuento cada vez que se crea una ventana e incrementando cada vez que se cierra una ventana. La aplicación especifica el objeto de semáforo en llamada a una de las funciones de espera antes de crear cada ventana. Cuando el recuento es cero, lo que indica que se ha alcanzado el límite de ventana, la función wait bloquea la ejecución del código de creación de ventanas.

Un subproceso usa la función CreateSemaphore o CreateSemaphoreEx para crear un objeto de semáforo. El subproceso de creación especifica el recuento inicial y el valor máximo del recuento para el objeto . El recuento inicial no debe ser menor que cero ni mayor que el valor máximo. El subproceso de creación también puede especificar un nombre para el objeto de semáforo. Los subprocesos de otros procesos pueden abrir un identificador en un objeto de semáforo existente especificando su nombre en una llamada a la función OpenSemaphore . Para obtener información adicional sobre los nombres de objetos mutex, event, semaphore y timer, vea Interprocess Synchronization.

Si hay más de un subproceso en espera en un semáforo, se selecciona un subproceso en espera. No asuma un orden primero en salir (FIFO). Los eventos externos, como las API en modo kernel, pueden cambiar el orden de espera.

Cada vez que una de las funciones de espera devuelve porque el estado de un semáforo se estableció en señalizado, el recuento del semáforo se reduce en uno. La función ReleaseSemaphore aumenta el recuento de un semáforo en una cantidad especificada. El recuento nunca puede ser menor que cero o mayor que el valor máximo.

El recuento inicial de un semáforo normalmente se establece en el valor máximo. A continuación, el recuento se reduce a partir de ese nivel a medida que se consume el recurso protegido. Como alternativa, puede crear un semáforo con un recuento inicial de cero para bloquear el acceso al recurso protegido mientras se inicializa la aplicación. Después de la inicialización, puede usar ReleaseSemaphore para incrementar el recuento al valor máximo.

Un subproceso que posee un objeto de exclusión mutua puede esperar repetidamente a que el mismo objeto de exclusión mutua se señale sin que su ejecución se bloquee. Un subproceso que espera repetidamente el mismo objeto de semáforo, sin embargo, disminuye el recuento del semáforo cada vez que se completa una operación de espera; el subproceso se bloquea cuando el recuento llega a cero. Del mismo modo, solo el subproceso que posee una exclusión mutua puede llamar correctamente a la función ReleaseMutex , aunque cualquier subproceso puede usar ReleaseSemaphore para aumentar el recuento de un objeto de semáforo.

Un subproceso puede disminuir el recuento de un semáforo más de una vez especificando repetidamente el mismo objeto de semáforo en llamadas a cualquiera de las funciones de espera. Sin embargo, llamar a una de las funciones de espera de varios objetos con una matriz que contiene varios identificadores del mismo semáforo no da lugar a varios decrementos.

Cuando haya terminado de usar el objeto de semáforo, llame a la función CloseHandle para cerrar el identificador. El objeto de semáforo se destruye cuando se ha cerrado su último identificador. Cerrar el controlador no afecta al recuento de semáforos; por lo tanto, asegúrese de llamar a ReleaseSemaphore antes de cerrar el identificador o antes de que finalice el proceso. De lo contrario, las operaciones de espera pendientes agotarán el tiempo de espera o continuarán indefinidamente, en función de si se ha especificado un valor de tiempo de espera.

Uso de objetos de semáforo