3

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

#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应该停止生产,当它小于 时Nproducer恢复生产。

奇怪的问题是,如果我删除sleep(1);in consumer,程序将运行segmentation fault,如果我保留sleep(1);,程序运行正常。

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

4

2 回答 2

4

虚假唤醒可能是原因。如果条件为真,您的线程将继续,但如果您的线程继续,您不能假设条件为真。

可能会发生来自 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);
}
于 2012-07-29T11:50:47.690 回答
1

如果您保持sleep(1)通话并且整个事情没有崩溃,那么您很幸运:)

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

文档

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.
于 2012-07-29T11:44:48.983 回答