В вашем коде есть несколько серьезных проблем.
- Мьютекс может быть разблокирован потоком, только если поток заблокировал его ранее.В вашем коде мьютекс заблокирован вне функции цикла и разблокирован внутри цикла.Это даст неопределенное поведение.
- Функция потребителя выполняет signal_wait () перед входом в цикл.Я думаю, вы предположили, что потоки производителя и потребителя запускаются почти одновременно, и производитель не будет сигнализировать, пока потребитель не заблокирует мьютекс.Это не верно. Вы должны предполагать, что потоки планируются в случайном порядке и обрабатывать все возможные случаи.
- Вы не уведомляете производителя, когда потребитель полностью использует данные.Не существует механизма сигнализации от потребителя к производителю.
- Вы уведомляете потребителя, когда производитель полностью произвел данные.Но потребитель не ждет снаружи пока цикл.Это означает, что только один раз он может получить уведомление.
- В продюсере условие condition_signal находится после разблокировки мьютекса, что неверно.Сигнал должен вызываться с заблокированным мьютексом.
Таким образом, в источнике необходимо создать данные, отправить сигнал потребителю и дождаться подтверждения от потребителя о том, что данные использованы.Вам необходимо дополнительно установить флаг, чтобы учесть случай, когда поток производителя получает блокировку перед потоком потребителя во внимание.В этом случае потребитель не вошел бы в цикл while, когда производитель посылает сигнал.Таким образом, потребитель не может поймать сигнал.
void *producer(void *arg)
{
pthread_mutex_lock(&mutex);
while(1)
{
printf("\n Enter no of terms");
scanf("%d",&n);
int i;
printf("\n Enter consumer flag array");
for (i = 0; i < n; i++)
{
scanf(" %d",&consumerFlag[i]);
//pthread_mutex_unlock(&mutex); //Should not be unlocked in loop
}
data_produced_flag = 1; //A flag to indicate data is ready. Should be initialized to 0 before thread creation. It is required if producer produces before consumer thread goes to pthread_cond_wait()
pthread_cond_signal(&cond_producer); //Should send signal with mutex locked
//usleep(1000); //Not required as it is going to wait for signal from consumer
pthread_cond_wait(&cond_consumer, &mutex); //Wait for confirmation that data is consumed
}
pthread_mutex_unlock(&mutex);
}
В функции потребителя, вы должны проверить, если данные уже получены.Если не произведено, дождитесь сигнала от производителя.Когда данные доступны, потребляйте и дайте сигнал производителю, чтобы получить свежие данные.
void *consumer(void *arg)
{
int i;
pthread_mutex_lock(&mutex);
//pthread_cond_wait(&cond, &mutex); //Wait inside loop
printf("\nConsumer Function");
while(1)
{
if(0 == data_produced_flag)
{
printf("\nConsumer thread waiting");
pthread_cond_wait(&cond_producer, &mutex); //Wait for signal from producer
}
//else
//{
//Data is already produced. No need to wait.
//}
//Data is available for consumption
for (i = 0; i < n; i++)
{
printf("\nConsumerFlag %d = %d", i, consumerFlag[i]);
//pthread_mutex_unlock(&mutex); //We are in the process of consumption. Don't unlock mutex.
}
data_produced_flag = 0; //Reset the flag. Ready for new data.
pthread_cond_signal(&cond_consumer); //Indicate that data is consumed
}
pthread_mutex_unlock(&mutex);
}