Как синхронизировать потоки (потребитель / производитель)

У меня есть следующий код:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <queue>
using namespace std;

queue<int> myqueue;

pthread_mutex_t count_mutex     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  condition_var   = PTHREAD_COND_INITIALIZER;

void *consumer(void*);
void *producer(void*);

#define COUNT_DONE 10
int count = 0;

main()
{
pthread_t thread1, thread2;

pthread_create( &thread2, NULL, &consumer, NULL);
pthread_create( &thread1, NULL, &producer, NULL);

pthread_join( thread1, NULL);
pthread_join( thread2, NULL);

printf("Final count: %d\n",count);

system("PAUSE");
return EXIT_SUCCESS;
}

void *consumer(void*)
{
for(;;)
{
// Lock mutex and then wait for signal to relase mutex
printf("consumer mutex lock \n");
pthread_mutex_lock( &count_mutex );
printf("consumer mutex locked\n");

// Wait while functionCount2() operates on count
// mutex unlocked if condition varialbe in functionCount2() signaled.
printf("consumer wait\n");
pthread_cond_wait( &condition_var, &count_mutex );
printf("consumer condition woke up\n");
myqueue.pop();count--;
printf("Counter value consumer: %d\n",count);

printf("consumer mutex unlock\n");
pthread_mutex_unlock( &count_mutex );

if(count >= COUNT_DONE) return(NULL);
}
}

void * producer(void*)
{
for(;;)
{
printf("producer mutex lock\n");
pthread_mutex_lock( &count_mutex );
printf("producer mutex locked\n");

if( count < COUNT_DONE)
{
myqueue.push(1);
count++;
printf("Counter value producer: %d\n",count);
printf("producer signal\n");
pthread_cond_signal( &condition_var );
}

printf("producer mutex unlock\n");
pthread_mutex_unlock( &count_mutex );

if(count >= COUNT_DONE) return(NULL);

Sleep(5000);
}

}

Этот пример отлично работает, когда потребительский поток первым получает мьютекс. Но потом, когда поток производителя сначала получает мьютекс, у меня всегда будет 1 целое число в очереди, которое потребитель не может вытолкнуть.

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

Примечание: я ищу лучший способ, чем запускать один поток раньше другого.

Спасибо,

0

Решение

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

Вторая проблема, которую я вижу, состоит в том, что вы увеличиваете счетчик в одном и уменьшаете его в другом, так как вы когда-либо достигаете условия завершения?

Возьмите ниндзя «count—» из потребителя, и он должен работать. Тем не менее, вы можете сделать следующее внутри потребителя:

// Wait for producer to do its thing and tell us there is work to do.
while ( myqueue.empty() ) {
pthread_cond_wait(&condition_var, &count_mutex);
}
// we've been told there's work to do with the queue,
// and we know there's something ON the queue.
// consume the entire queue.
while ( !myqueue.empty() ) {
myqueue.pop();
}

// treat count as protected by the mutex, so hoist this test into the lock.
bool workDone = (count >= COUNT_DONE);
pthread_mutex_unlock(&count_mutex);

if(workDone)
return break;

редактировать: предпочтительная версия потребителя:

bool workDone = false;
while(workDone == false)
{
// Lock mutex and then wait for signal to relase mutex
pthread_mutex_lock( &count_mutex );

// Wait for producer to do its thing and tell us there is work to do.
while ( myqueue.empty() )
pthread_cond_wait( &condition_var, &count_mutex );

// we've been told there's work to do with the queue,
// and we know there's something ON the queue.
// consume the entire queue.
while ( myqueue.empty() == false ) {
myqueue.pop();
}

// count is protected by the lock so check if we're done before we unlock.
workDone = (count >= COUNT_DONE);
pthread_mutex_unlock( &count_mutex );

}
return NULL;
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector