Pregunta

Estoy intentando un problema de varios productores / consumidores en C, pero no funciona como se esperaba. El siguiente es un pseudo código para representar mi implementación.

Thread thread1;
Thread thread2;
Thread thread3;

Data data1;
Mutex data1_mutex;
Semaphore data1_empty;
Semaphore data1_fill;

Data data2;
Mutex data2_mutex;
Semaphore data2_empty;
Semaphore data2_fill;

thread1()
{
   // creates data and places it into data1.

   wait(data1_empty);
   lock(data1_mutex);

   // critical section

   unlock(data1_mutex);
   post(data1_fill);
}

thread2()
{
   // Removes data from data1, processes it, and places it into data2.

   // data1
   wait(data1_fill);
   lock(data1_mutex);

   // data2
   wait(data2_empty);
   lock(data2_mutex);

   // critical section

   // data2
   unlock(data2_mutex);
   post(data2_fill);

   // data1
   unlock(data1_mutex);
   post(data1_empty);
}

thread3()
{
   // Removes data from data2, prints its results, and removes it.

   wait(data2_fill);
   lock(data2_mutex);

   // critical section

   unlock(data2_mutex);
   post(data2_empty);
}

Sin embargo, con esta solución, los datos1 se llenarán, pero el hilo2 se bloqueará y nunca se ejecutará. ¿Hay algún problema con mi implementación?

EDIT # 1

Uno de los problemas que encontré fue que mi segundo mutex no se estaba creando correctamente. No sé qué tiene de malo, así que solo uso el primer mutex para todos los subprocesos. También hay algo más que he hecho para que funcione, así que actualizaré mi pseudocódigo para reflejar esto más adelante cuando tenga un minuto.

¿Fue útil?

Solución

Asegúrate de publicar data1_empty y data2_empty inicialmente.

Otros consejos

Si utiliza algún tipo de tipo de cola para Data , debería poder eliminar el " vacío " semáforos completamente, a menos que esté tratando de imponer la condición de que cada profundidad de la cola Data sea estrictamente 0 o 1. Si usa una variable local en thread2 , puede reducir la Tamaño de la sección crítica.

El código se convierte en algo como esto:

thread1() {
    //Wait for data to put in the queue (i.e. a blocking socket read)
    lock(data1_mutex);
    data1.push(someData);
    unlock(data1_mutex);
    post(data1_fill);
}

thread2() {
    DataType dataElement;
    wait(data1_fill);
    lock(data1_mutex);
    dataElement = data1.pop();
    unlock(data1_mutex);

    lock(data2_mutex);
    data2.push(dataElement);
    unlock(data2_mutex);
    post(data2_fill);
}

thread3() {
    DataType dataElement;
    wait(data2_fill);
    lock(data2_mutex);
    dataElement = data2.pop();
    unlock(data2_mutex);
    //do something with dataElement here
}

Lo que dijo el wrang-wrang, e intenta no mantener el bloqueo de data_1 mientras esperas a data_2_empty. Puedes lograr esto manteniendo un búfer alternativo para data_1 y data_2 que intercambias. Thread_2 intercambia datos_1 mientras lo procesa en data_2, thread_3 intercambia datos_2 mientras lo procesa. Su pseudocódigo actual permitirá que el subproceso 1 y el subproceso 3 se ejecuten simultáneamente, pero no permitirá que el subproceso 2 se ejecute al mismo tiempo que cualquiera de los otros.

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