生产者和消费者 - 多线程

producer & consumer - multithreading

本文关键字:多线程 消费者 生产者      更新时间:2023-10-16

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

#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 createdn");
    sleep(600);
}

qu.size()大于N时,producer应停止生产,当小于N时,producer恢复生产。

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

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

错误的唤醒可能是原因。如果条件为true,则线程将继续,但如果线程继续,则不能假设条件为true。

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

如果你保留了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.