En el estudio y uso de los semáforos se puede ver que las llamadas a las funciones necesarias para utilizarlos quedan repartidas en el código del programa, haciendo difícil corregir errores y asegurar el buen funcionamiento de los algoritmos.
El concepto de monitor fue definido por primera vez por Charles Antony Richard Hoare en un artículo del año 1974.
Los monitores están pensados para ser usados en entornos multiproceso o multihilo, y por lo tanto muchos procesos o hilos pueden llamar a la vez a un procedimiento del monitor.
De esta forma, si un thread llama a un procedimiento mientras otro thread está dentro del monitor, se bloqueará y esperará en la cola de entrada hasta que el monitor quede nuevamente libre.
Más tarde, cuando la condición permita al thread bloqueado continuar ejecutando, debe poder ingresar en el monitor en el mismo lugar donde fue suspendido.
Para esto los monitores poseen variables de condición que son accesibles solo desde adentro.
Si otro thread provoca un evento, simplemente utiliza la función cond_signal con esa condición como parámetro.
Según quién continúa con la ejecución, se diferencian dos tipos de monitores: Hoare y Mesa.
El monitor toma entonces el lock y se lo entrega al thread durmiente, que reanuda la ejecución.
Más tarde cuando el monitor quede libre nuevamente el thread que cedió el lock volverá a ejecutar.
Si hay otro thread esperando en esa variable de condición, se lo despierta y deja como listo.
En el proceso que durmió, por lo tanto, es necesario cambiar la instrucción if por while, para que al despertar compruebe nuevamente la condición, y de no ser cierta vuelva a llamar a cond_wait.
En monitores con señales desplazantes, cond_signal y cond_wait hacen referencia a estados visibles del programa.
Por lo tanto, debe verificar el Invariante del monitor antes de que pueda ejecutarse.
[1] cond_wait, al igual que con señales desplazantes, bloquea el proceso y cede el uso del monitor.
Cuando el proceso en espera vuelva a ser ejecutado, debe garantizarse que el invariante del monitor sigue siendo válido.
Así, las invariantes establecen las condiciones que deben cumplirse todo el tiempo y las reglas de prueba establecen las condiciones que deben cumplirse cuando un proceso solicita un recurso del monitor.
Un simple ejemplo de las reglas de prueba es el problema del productor y el consumidor, donde un productor desea continuar produciendo un objeto, pero no puede sobrepasar el número máximo de objetos mientras un consumidor desea consumir el mismo objeto, pero no puede consumir si la lista está vacía.
Por otro lado, las invariantes serían los límites de la estructura que almacena los objetos producidos.