Alcott
Alcott

Reputation: 18595

producer & consumer - multithreading

I wrote a multithreading program like this,

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

When the qu.size() is geater than N, producer should stop producing, and when it's less than N, producer resumes producing.

The weired problem is, if I remove the sleep(1); in consumer, the program will run into segmentation fault, if I keep sleep(1);, the program runs ok.

Why? Does it mean the consumer consumes too fast?

Upvotes: 3

Views: 1660

Answers (2)

Viktor Latypov
Viktor Latypov

Reputation: 14467

If you keep the sleep(1) call and the whole thing does not crash you're just lucky :)

Try initializing the mutex explicitly using the pthread_mutex_init() otherwise your pthread_mutex_lock() calls seem to fail.

From 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.

Upvotes: 1

John Watts
John Watts

Reputation: 8885

Spurious wakeup might be the reason. Your thread will proceed if the condition is true, but if your thread proceeds you can't assume the condition is true.

Spurious wakeups from the pthread_cond_timedwait() or pthread_cond_wait() functions may occur. Since the return from pthread_cond_timedwait() or pthread_cond_wait() does not imply anything about the value of this predicate, the predicate should be re-evaluated upon such return.

So for example

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

should become

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

Upvotes: 4

Related Questions