Pergunta

Eu estou tentando um problema múltiplo produtor / consumidor em C, mas não o seu trabalho como esperado. O seguinte é algum código pseudo para representar minha implementação.

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);
}

No entanto, com esta solução data1 vai encher-se, mas thread2 irá travar e nunca executado. Há algo de errado com a minha implementação?

EDIT # 1

Um dos problemas que eu encontrei foi que a minha segunda mutex não estava sendo criado corretamente. Eu não sei o que está errado com ele assim que eu estou usando apenas o primeiro de exclusão mútua para todos os tópicos. Há também uma outra coisa que eu fiz para fazê-lo funcionar, então eu vou atualizar meu pseudo-código para refletir isso mais tarde quando eu tenho um minuto.

Foi útil?

Solução

Certifique-se de pós data1_empty e data2_empty inicialmente.

Outras dicas

Se você usar algum tipo de fila tipo para Data, você deve ser capaz de remover os semáforos "vazios" completamente, a menos que você está tentando impor a condição de que cada profundidade da fila Data é estritamente 0 ou 1. Se você usar uma variável local em thread2, você pode reduzir o tamanho da seção crítica.

O código torna-se então algo como isto:

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
}

O que wrang-wrang disse, e não tentar manter o bloqueio para dados_1 enquanto você está esperando para data_2_empty. Você poderia conseguir isso, mantendo um tampão alternativo para dados_1 e dados_2 que você trocar. Thread_2 swaps dados_1 ao processar-lo em dados_2, thread_3 swaps fora dados_2 enquanto processá-lo. Seu pseudo-código atual permitirá linha 1 e linha 3 para executar simultaneamente, mas não permitirá fio 2 para executar ao mesmo tempo que qualquer um dos outros.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top