C - проблема тупика производителя / потребителя - PullRequest
2 голосов
/ 05 ноября 2010

Я пытаюсь работать с потоками производителя / потребителя в ограниченном буфере.Длина буфера равна 5. У меня есть 1 мьютекс и 2 семафора, пустой, который начинается с размера буфера, и полный, который начинается с 0.

Когда я запускаю свой код без sleep () вконец, он непрерывно производит до тех пор, пока буфер не будет полностью заполнен, потребляет, пока он не станет пустым, поэтому вывод выглядит так:

Placed 1 in the buffer at position 0.
Placed 2 in the buffer at position 1.
Placed 3 in the buffer at position 2.
Placed 4 in the buffer at position 3.
Placed 5 in the buffer at position 4.
The buffer now contains 0 at position 0.
The buffer now contains 0 at position 1.
The buffer now contains 0 at position 2.
The buffer now contains 0 at position 3.
The buffer now contains 0 at position 4.

Однако, когда я запускаю с sleep () в конце, он печатаетout:

Placed 1 in the buffer at position 0.
The buffer now contains 0 at position 0.

Затем кажется, что он заблокирован, но я не совсем уверен, почему он ведет себя так, как он делает, независимо от того, спит или нет.Какие-либо предложения?Мой основной метод по сути просто делает некоторые объявления, затем создает 1 поток для производства и 1 для потребления, эти методы приведены ниже.

void *producer()
{
        int k = 0; //producer index
        while (1)
        {
                sem_wait(&empty);
                pthread_mutex_lock(&mutex);
                buffer[k] = k+1;
                sem_post(&full);
                pthread_mutex_unlock(&mutex);
                printf("Placed %d in the buffer at position %d.\n", buffer[k], k);
                k = (k + 1) % BUFFER_SIZE;
                sleep(rand() * 10);
        }
}

void *consumer()
{
        int j = 0;   //consumer index
        while(1)
        {
                sem_wait(&full);
                pthread_mutex_lock(&mutex);
                buffer[j] = 0;
                sem_post(&empty);
                pthread_mutex_unlock(&mutex);
                printf("The buffer now contains %d at position %d.\n", buffer[j], j);
                j = (j + 1) % BUFFER_SIZE;
                sleep(rand() * 10);

        }
}

Ответы [ 4 ]

3 голосов
/ 05 ноября 2010

Параметр на sleep() - это количество секунд, в течение которого нужно спать.rand() возвращает целое число от 0 до RAND_MAX (обычно 32767 или 2 31 -1), и когда вы умножаете это на 10, вы спите в течение абсурдно большого количества времени.Вы не зашли в тупик, просто спите очень долго.

2 голосов
/ 05 ноября 2010

Я не знаю, является ли это причиной вашей тупиковой ситуации, но вы должны быть осторожны с sem_t функциями, они подвержены прерываниям, в частности из-за ввода-вывода и тому подобного.

Никогда не игнорируйте возврат из системных функций. Здесь вы должны проверить возврат, а затем errno для EINTR.

Тогда я не знаю, если вы вынуждены использовать sem_t, но я думаю, что более естественным здесь было бы использование pthread_cond_t. В любом случае, у вас есть мьютекс, так что это будет проще. pthread_cond_t, поскольку pthread_mutex_t функции никогда не прервутся.

1 голос
/ 05 ноября 2010

Do you have any idea why when I don't include sleep it always produces and consumes in blocks instead of every other?

Вероятно, потому, что интервал времени ~ 30 мс, который дается каждому потоку, более чем достаточен для того, чтобы производитель мог произвести все до того, как произойдет переключение контекста.

0 голосов
/ 05 ноября 2010

Я полагаю, что оба ваших потока имеют одинаковый приоритет?И это на машине с несколькими ядрами или только на одном?Простая сигнализация семафора не приведет к вытеснению вашего текущего потока, поэтому ожидается, что текущий поток будет продолжать работу до истечения срока его среза.

Кроме того, я определенно разблокирую мьютекс перед тем, как подать сигнал на мьютекс.*

...