Es solo la forma en que las variables de condición se implementan (o fueron originalmente).
El mutex se utiliza para proteger la variable de condición en sí . Por eso es necesario que lo bloquees antes de esperar.
La espera "atómicamente" desbloqueará el mutex, permitiendo que otros accedan a la variable de condición (para señalización). Luego, cuando se señala o se transmite la variable de condición, se despertará uno o más subprocesos en la lista de espera y el mutex se bloqueará mágicamente nuevamente para ese subproceso.
Por lo general, ve la siguiente operación con variables de condición, que ilustra cómo funcionan. El siguiente ejemplo es un subproceso de trabajo al que se le da trabajo mediante una señal a una variable de condición.
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
do the work.
unlock mutex.
clean up.
exit thread.
El trabajo se realiza dentro de este ciclo siempre que haya algo disponible cuando regrese la espera. Cuando el hilo se ha marcado para dejar de funcionar (normalmente otro hilo configura la condición de salida y luego patea la variable de condición para activar este hilo), el bucle saldrá, el mutex se desbloqueará y este hilo saldrá.
El código anterior es un modelo de consumidor único ya que el mutex permanece bloqueado mientras se realiza el trabajo. Para una variación de múltiples consumidores, puede usar, como ejemplo :
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
copy work to thread local storage.
unlock mutex.
do the work.
lock mutex.
unlock mutex.
clean up.
exit thread.
lo que permite que otros consumidores reciban trabajo mientras este está trabajando.
La variable de condición lo libera de la carga de sondear alguna condición, permitiendo que otro hilo le notifique cuando algo debe suceder. Otro hilo puede decir que ese hilo que funciona está disponible de la siguiente manera:
lock mutex.
flag work as available.
signal condition variable.
unlock mutex.
La gran mayoría de lo que a menudo se llama erróneamente despertares espurios generalmente se debe a que se han señalado múltiples hilos dentro de su pthread_cond_wait
llamada (transmisión), uno volvería con el mutex, haría el trabajo y luego volvería a esperar.
Entonces el segundo hilo señalado podría salir cuando no había trabajo que hacer. Por lo tanto, tenía que tener una variable adicional que indicara que el trabajo debería hacerse (esto estaba inherentemente protegido por mutex con el par condvar / mutex aquí; sin embargo, se necesitaban otros hilos para bloquear el mutex antes de cambiarlo).
Que era técnicamente imposible que un hilo para volver a una condición de espera sin ser expulsado por otro proceso (esto es un verdadero despertar espuria), pero, en todos mis muchos años trabajando en pthreads, tanto en el desarrollo / servicio del código y como usuario De ellos, nunca recibí uno de estos. Tal vez eso fue solo porque HP tuvo una implementación decente :-)
En cualquier caso, el mismo código que manejó el caso erróneo también manejó despertadores falsos genuinos, ya que el indicador de trabajo disponible no se establecería para esos.