2
votes

After searching on the web, and reading the question answers on the stackoverflow, i couldn't find the answer of my question.

The wait is called in thread B, and it unlocks the mutex, allowing others access to the condition variable (for signalling). Then, when the condition variable is signalled in thread A , thread B wakes up and Thread B locks the mutex again.

When the thread A wakes up thread B by signalling the condition variable, thread B is waked up, lock the mutex.

I understand from the tutorials that, whenever thread B is signaled, it immediately locks the mutex. However the examples are the opposite of this, when thread B is signaled,and waked up, thread A continue to execute, some times later thread B locks the mutex.

My question is when does thread B(consumer in the below example) lock the mutex? Just at the moment that thread B takes the signal? Or does it depend on the thread scheduler?

I didn't find any explanations about that.

I am thinking about the case of below example :

#include <pthread.h>
#include <stdio.h>

pthread_mutex_t mutex;
pthread_cond_t cond;

int buffer[100];

int loops = 5;
int length = 0;

void *producer(void *arg) {
    int i,j;
    for (i = 0; i < loops; i++) {
    pthread_mutex_lock(&mutex);
    buffer[length++] = i;
    printf("producer length %d\n", length);
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
    }
}

void *consumer(void *arg) {
    int i;
    for (i = 0; i < loops; i++) {
    pthread_mutex_lock(&mutex);
    while(length == 0) {
        printf(" consumer waiting...\n");
        pthread_cond_wait(&cond, &mutex);
    }
    int item = buffer[--length];
    printf("Consumer %d\n", item);
    pthread_mutex_unlock(&mutex);
    }
}

int main(int argc, char *argv[])
{

    pthread_mutex_init(&mutex, 0);
    pthread_cond_init(&cond, 0);

    pthread_t pThread, cThread;
    pthread_create(&pThread, 0, producer, 0);
    pthread_create(&cThread, 0, consumer, 0);
    pthread_join(pThread, NULL);
    pthread_join(cThread, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

Output :

consumer waiting...
producer length 1
producer length 2
producer length 3
producer length 4
producer length 5
Consumer 4
Consumer 3
Consumer 2
Consumer 1
Consumer 0

THanks in advance

3

3 Answers

6
votes

The behavior of a condition variable is that of releasing the lock and waiting (atomically) and then re-acquiring the lock when the thread is signaled. In your code, one thread is signaling the other while holding the mutex, and the implication is that the woken up thread is going to enter the wait queue in the mutex until the other thread releases the mutex.

0
votes

Thread B (consumer) wakes up with the mutex already acquired, assuming pthread_cond_unlock returns successfully. So you want to check for the return value (i.e. 0 = successful) to know whether the mutex was acquired.

-1
votes

I just want to add here my two cents with regards to a less-obvious implied behavior when working with pthread condition variable + a mutex. Considere the sequence below:

pthread_mutex_lock(&m);
pthread_con_wait(&cond,&m);
pthread_mutex_unlock(&m);

As soon as the thread has waited on 'cond', it also automatically unlocks the mutex!! This is not obvious, and has caused a lot of confusion.