生产者和消费者 - 多线程

时间:2012-07-29 11:17:21

标签: c++ multithreading

我写了一个像这样的多线程程序,

#include <queue>
#include <cstdio>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ec = PTHREAD_COND_INITIALIZER;
pthread_cond_t fc = PTHREAD_COND_INITIALIZER;

queue<int> qu;
const int N = 2;

void *producer(void *arg)
{
    while(1) {
        pthread_mutex_lock(&mu);
        int tmp = rand();
        qu.push(tmp);
        pthread_cond_signal(&ec);
        if ((int) qu.size() > N) {
            pthread_cond_wait(&fc, &mu);
        }
        pthread_mutex_unlock(&mu);
    }
}

void *consumer(void *arg)
{
    while(1) {
        pthread_mutex_lock(&mu);
        if ((int) qu.size() < 1) {
            pthread_cond_wait(&ec, &mu);
        }
        int tmp = qu.front();
        qu.pop();
        if ((int) qu.size() <= N) {
            pthread_cond_signal(&fc);
        }
        pthread_mutex_unlock(&mu);
        //sleep(1);
    }
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, NULL, producer, NULL);
    for (int i = 0; i < N; i++) {
        pthread_t tid;
        pthread_create(&tid, NULL, consumer, NULL);
    }

    printf("all created\n");

    sleep(600);
}

如果qu.size()N更好,producer应该停止生成,当它小于N时,producer会恢复生成。

我们遇到的问题是,如果我删除了sleep(1);中的consumer,程序会遇到segmentation fault,如果我保留sleep(1);,程序就会运行正常。< / p>

为什么呢?这是否意味着consumer消耗得太快了?

2 个答案:

答案 0 :(得分:4)

Spurious wakeup可能是原因。如果条件为真,你的线程将继续,但如果你的线程继续,你不能认为条件是真的。

  

可能会发生pthread_cond_timedwait()或pthread_cond_wait()函数的虚假唤醒。由于从pthread_cond_timedwait()或pthread_cond_wait()返回并不意味着有关此谓词的值的任何内容,因此应在返回时重新评估谓词。

所以例如

if (qu.size() == 0) {
    pthread_cond_wait(&ec, &mu);
}

应该成为

while (qu.size() == 0) {
    pthread_cond_wait(&ec, &mu);
}

答案 1 :(得分:1)

如果你保持sleep(1)电话,整个事情都不会崩溃,那你就是幸运的。)

尝试使用pthread_mutex_init()显式初始化互斥锁,否则你的pthread_mutex_lock()调用似乎失败。

来自the docs

Errors

The pthread_mutex_lock() and pthread_mutex_trylock()
functions may fail if: 

EINVAL: The value specified by mutex
does not refer to an initialized mutex object.