Pregunta

Tengo un escenario simple productor / consumidor, donde hay solo un único elemento que se está producida / consumida. Además, el productor espera el subproceso de trabajo termine antes de continuar. Soy consciente de que tipo de obvie el punto central de multi-hilo, pero por favor, simplemente asumen que realmente tiene que ser de esta manera (:

Este código no se compila, pero espero que la idea:

// m_data is initially null

// This could be called by any number of producer threads simultaneously
void SetData(object foo)
{
    lock(x)                      // Line A
    {
        assert(m_data == null);
        m_data = foo;
        Monitor.Pulse(x)         // Line B
        while(m_data != null)
            Monitor.Wait(x)      // Line C
    }
}

// This is only ever called by a single worker thread
void UseData()
{
    lock(x)                      // Line D
    {
        while(m_data == null)
            Monitor.Wait(x)      // Line E
        // here, do something with m_data
        m_data = null;
        Monitor.Pulse(x)         // Line F
    }
}

Esta es la situación que no estoy seguro acerca de:

Supongamos que muchos hilos llaman SetData () con diferentes entradas. Sólo uno de ellos conseguirá dentro de la cerradura, y el resto se bloquearán en la Línea A. Supongamos que el que tiene en el interior de los conjuntos de bloqueo M_DATA y hace su camino a la línea C.

Pregunta: ¿Podría la espera () en la línea C permitir que otro hilo en la línea A para obtener el bloqueo y la sobreescritura M_DATA antes de que el subproceso de trabajo incluso llega a ella

?

Suponiendo que no sucede, y el hilo de los procesos de trabajo del original M_DATA , y, finalmente, se abre paso a la línea F, lo que sucede cuando ese impulso () se apaga?

Será sólo el hilo de espera en la línea C será capaz de obtener el bloqueo? O va a estar compitiendo con todos los otros hilos esperando en la línea A, así?

En esencia, me gustaría saber si el pulso () / espera () se comunican entre sí especialmente "bajo el capó" o si están en el mismo nivel con el bloqueo ().

La solución a estos problemas, si es que existen, es obvio, por supuesto - sólo SetData envolvente () con otro bloqueo - por ejemplo, bloqueo (y). Tengo curiosidad de si es aún un problema para empezar.

¿Fue útil?

Solución

No hay ninguna garantía de que el consumidor se pone en cola en la cola de espera o listos antes de que otro productor.
C # y Java monitores estilo se describen en Wikipedia, bajo "implícitos condición monitores" .
Una visión agradable de lo que ocurre en Monitor (tomado de este excelente sitio ): texto alternativo ??

  

"¿Puede la espera () en la línea C permitir que otro hilo en la línea A para obtener el bloqueo y M_DATA sobrescritura antes de que el subproceso de trabajo incluso llega a ella?"

Supongamos que SetData() es llamado por dos hilos de productores, P1 & P2 .
Un hilo consumidor, C1 se inicia también.
P1 , P2 y C1 todos entran en la cola de listos.
P1 adquiere el bloqueo en primer lugar.
La cola de espera está vacía, Pulse() en line B no tiene ningún efecto.
P1 espera en line C, por lo que se coloca en la cola de espera.
El siguiente hilo en la cola de listos adquiere la cerradura.
Puede ser igualmente P2 o C1 - en el primer caso, la afirmación no
. Usted tiene una condición de carrera.

  

"Suponiendo que no sucede, y el subproceso de trabajo procesa la M_DATA original, y, finalmente, se abre paso a la línea F, lo que sucede cuando ese impulso () se apaga?"

Se moverá un camarero de la cola de espera de la cola de listos.
El bloqueo se mantiene por el hilo que las cuestiones del Pulse().
El hilo será notificado tener la oportunidad para adquirir el bloqueo después de liberar el hilo pulsante la cerradura (que ya puede haber otros en la cola de listos).
De de MSDN, monitor .pulse () :
"El hilo que posee actualmente el bloqueo en el objeto especificado invoca este método para indicar el siguiente hilo en la línea de la cerradura. Al recibir el pulso, el hilo de espera se mueve a la cola de listos. Cuando el hilo que pulso invoca libera el bloqueo, el siguiente hilo en la cola de listo (que no es necesariamente el hilo que se pulsó) adquiere el bloqueo ".

  

"Será sólo el hilo esperando en la línea C será capaz de obtener el bloqueo? ¿O va a estar compitiendo con todos los otros hilos esperando en la línea A, así?"

Todos los hilos que están en la cola de listos "competir" por tener la cerradura siguiente.
No importa si llegaron allí recta o de la cola de espera por medio de Pulse().

Las "colas" pueden ser implementadas por otros medios. (No es la cola estructura de datos como tal).
De esta manera una implementación Monitor no puede garantizar la equidad - pero puede tener rendimiento / rendimiento general más alto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top