Читатель не выходит из темы - Posix Pthreads - PullRequest
0 голосов
/ 20 апреля 2019

Я должен создать решение проблемы читателей и писателей с помощью posix pthreads, я сжал свой код до псевдокода, смешанного с C, чтобы уменьшить размер кода.

Поток записи завершается нормально, но потоки чтения никогда не завершаются / не завершаются, поэтому Reader join ждет вечно, и программа зависает.

Я полагаю, что это связано с условием ожидания pthread_cond_wait(&qElement, &mutex); в функции чтения. Возможно, он ожидает завершения потока записывающего устройства. Я попытался инкапсулировать его с if(!finished), поэтому он ждет только, если писатель все еще активен, но это все еще не работает.

Я не уверен, что делать, и считаю, что это логическая ошибка с моей обработкой pthread.

Был бы очень признателен за помощь.

Global variables in header file : 

#define TRUE 1
#define FALSE 0

int finished = FALSE

pthread_cond_t qServiced = PTHREAD_COND_INITIALIZER;
pthread_cond_t qEmpty = PTHREAD_COND_INITIALIZER;
pthread_cond_t qElement = PTHREAD_COND_INITIALIZER;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int main()
{
    Create 1 writer thread
    Create 2 reader threads

    Writer join <- Success 
    Reader join <- Program hangs here


void* writer()
{
    int totalQueued = 0; 
    int tasks = 20; 

    while(!finished)
    {
        pthread_mutex_lock(&mutex); 

        while(isFull(q))
        {
            pthread_cond_wait(&qEmpty, &mutex); 
        }

        if(totalQueued < tasks)
        {
            for(j = 0; j < 2; j++) //Add 2 numbers at a time 
            {
                if(!(isFull(q)))
                {
                    //Assume random numbers added to queue 
                    totalQueued++;
                }
            }
            pthread_cond_signal(&qElement);
            pthread_cond_wait(&qServiced, &mutex);
        }
        else
        {
            finished = TRUE; 
        }
        pthread_mutex_unlock(&mutex); 
    } 

    //Thread exits
}

void* reader()
{
    while(!finished)
    {
        pthread_mutex_lock(&mutex);

        while(isEmpty(q)) //If the queue is empty 
        {
            pthread_cond_signal(&qEmpty);
            pthread_cond_wait(&qElement, &mutex);
        }

        int n = dequeue(q); 
        printf("%d\n", n); 

        pthread_cond_signal(&qServiced); //Signal that task has been serviced
        pthread_mutex_unlock(&mutex);
    }
}

1 Ответ

1 голос
/ 20 апреля 2019

Вы представили только набросок вашего кода, я не могу выполнить полный анализ, но даже набросок показывает недостаток в вашем подходе.Когда писатель делает новые данные доступными, он разблокирует один считыватель:

            pthread_cond_signal(&qElement);

Если оба читателя ждут, когда писатель публикует последние произведения (которые появляютсяскорее всего), тогда останется ждать, когда писатель завершит работу.

Лучшие решения вращаются вокруг использования pthread_cond_broadcast() вместо или в дополнение к pthread_cond_signal().Было бы неплохо просто заменить последнее на первое, поскольку ваши читатели должны защищать себя от ложных пробуждений в любом случае (и, похоже, они действительно есть).Однако, если вы предпочитаете, вы можете настроить трансляцию писателя непосредственно перед его завершением или трансляцию основного потока после его присоединения к автору.

Кроме того, я склонен считать, что вы используете многобольше резюме, чем вам нужно на самом деле.Скорее всего, вы можете использовать только один, который будет проще как писать, так и рассуждать.

...