C++ 如何同步线程(使用者/生产者)

C++ 如何同步线程(使用者/生产者),c++,pthreads,condition-variable,C++,Pthreads,Condition Variable,我有以下代码: #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

我有以下代码:

#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);
    }

}
#包括
#包括
#包括
#包括
使用名称空间std;
队列myqueue;
pthread\u mutex\u t count\u mutex=pthread\u mutex\u初始值设定项;
pthread_cond_t condition_var=pthread_cond_初始值设定项;
无效*消费者(无效*);
无效*制作人(无效*);
#定义完成的计数为10
整数计数=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(“最终计数:%d\n”,计数);
系统(“暂停”);
返回退出成功;
}
无效*消费者(无效*)
{
对于(;;)
{
//锁定互斥锁,然后等待信号释放互斥锁
printf(“使用者互斥锁”);
pthread_mutex_lock(&count_mutex);
printf(“用户互斥锁\n”);
//函数count2()正在对计数进行操作,请稍候
//如果functionCount2()中的条件变量发出信号,互斥锁将解锁。
printf(“消费者等待”);
pthread\u cond\u wait(&condition\u var,&count\u mutex);
printf(“消费者状况已唤醒\n”);
myqueue.pop();计数--;
printf(“计数器值使用者:%d\n”,计数);
printf(“用户互斥锁解锁\n”);
pthread_mutex_unlock(&count_mutex);
如果(计数>=计数完成)返回(空);
}
}
无效*生产者(无效*)
{
对于(;;)
{
printf(“生产者互斥锁”);
pthread_mutex_lock(&count_mutex);
printf(“生产者互斥锁\n”);
如果(计数<计数\u完成)
{
myqueue.push(1);
计数++;
printf(“计数器值生成器:%d\n”,计数);
printf(“生产者信号”);
pthread_cond_信号(&condition_var);
}
printf(“生产者互斥锁解锁\n”);
pthread_mutex_unlock(&count_mutex);
如果(计数>=计数完成)返回(空);
睡眠(5000);
}
}
当使用者线程首先使用互斥锁时,这个示例可以很好地工作。但是,当生产者线程最初获取互斥锁时,队列中始终有1个整数,使用者无法弹出

如何让使用者线程在生产者之前首先获取互斥

注意:我正在寻找一种比先启动一个线程再启动另一个线程更好的方法


谢谢,

我看到的一个问题是,您的消费者实际上并没有检查要做的工作,而是盲目地从队列中弹出

我看到的第二个问题是,一个增加计数,另一个减少计数,那么如何达到终止条件呢

把忍者“计数--”从消费者身上拿出来,它应该会起作用。不过,您可能希望在消费者内部执行以下操作:

// 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;
编辑:消费者的首选版本:

// 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;