Ответ на ваш вопрос заключается в том, что вы делаете pthread_join () для потока перед созданием нового потока. Это означает, что вы выходите из первого потока перед началом нового потока. Таким образом, все операции полностью последовательны.
Вы должны запустить оба потока и затем присоединиться к ним, как показано ниже.
pthread_create(&pThread, 0, producer, 0); //Check return value and handle error
pthread_create(&cThread, 0, consumer,0); //Check return value and handle error
pthread_join(pThread,NULL);
pthread_join(cThread, NULL);
Но в вашем коде есть еще одна проблема. В функции consumer () вы разблокируете мьютекс внутри цикла. Я предполагаю, что вы хотите, чтобы пользователь прочитал один ввод от пользователя в потоке производителя и напечатал это входное значение в потоке потребителя. В этом случае вы должны переместить вызов разблокировки мьютекса за пределы цикла. Обратите внимание, что pthread_cond_wait () внутренне разблокирует мьютекс во время ожидания. Кроме того, вам необходимо напечатать значение после pthread_cond_wait()
, чтобы убедиться, что пользователь ввел введенное значение.
pthread_mutex_lock(&mutex);
for (i = 0; i < n; i++)
{
pthread_cond_wait(&cond, &mutex);
printf("%d\n",buffer[i]);
}
pthread_mutex_unlock(&mutex);
Я написал этот ответ только для интересной части ниже!
Вызов pthread_create (); для потока не означает, что поток начинает работать немедленно. Несколько потоков могут работать в случайном (следует предполагать) порядке.
Итак. Если потребительский поток запускается очень поздно, т. Е. Если он запускается после двух или более pthread_cond_signal(&cond);
из потока производителя, то потребительский поток войдет в тупиковую ситуацию, так как он выполняет точное число вызовов pthread_cond_wait()
. Обратите внимание, что pthread_cond_signal()
пропускается, если ни один поток не выполняет pthread_cond_wait()
в этот момент времени.
Итак ... вам нужно убедиться, что потребительский поток запущен перед тем, как начать читать входные данные из потока производителя.
Есть несколько способов добиться этого. Одним из способов является опрос с использованием глобального флага и мьютекса. (Для этого вы можете использовать другую комбинацию мьютекс-условие-сигнал.)
void *producer(void *arg) {
while(1) {
pthread_mutex_lock(&mutex);
if(1 == consumerStartedFlag) {
pthread_mutex_unlock(&mutex);
break;
}
pthread_mutex_unlock(&mutex);
usleep(1000); //Sleep for 1ms to prevent this thread from consuming large CPU
}
//Rest of the producer functionality
}
void *consumer(void *arg) { // For printing the input array
pthread_mutex_lock(&mutex);
consumerStartedFlag = 1; //Global flag, intialize it to zero in main before starting threads.
pthread_mutex_unlock(&mutex);
//Rest of the consumer functionality
}
Теперь, если производитель запускается первым, он будет ждать в цикле while
. Если потребитель запускается первым, он будет ждать в pthread_cond_wait()
.
Обновление 1 На основе комментария ниже.
В продюсере () scanf () находится внутри блокировки мьютекса. Это заблокирует потребителя на неопределенный срок. Таким образом, вы можете не получить вывод правильно. Поэтому установите scanf () вне блокировки, как показано ниже.
scanf(" %d",&buffer[i]); //Remove '\n' from scanf() as it will block your scanf call.
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);