0

I have written the following code to get the understanding of event ordering using pthreads and mutex. main function creates two threads which are associated to functions func1 and func2. Function func1 checks for the value of count and conditionally wait for func2 to signal it. Function func2 increments the count and when count reaches 50000, it signals func1. Then func1 prints the value of count which is(or should be) at that time 50000.

But in actual output, along with 50000 some other values are also being printed. I am not getting any reason why is it so. What I think is, when func2 signals, func1 wakes up and execute from after the pthread_cond_wait statement, and so it should print only 50000. Please point out where I am wrong and what should be changed to get correct output?

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


pthread_mutex_t evmutex;
pthread_cond_t evcond;

char a;
int count;
int N = 50000;

void *func1()
{
    while(1)
    {
        pthread_mutex_lock(&evmutex);
        if(count < N)
        {
            pthread_cond_wait(&evcond,&evmutex);
            printf("%d\n",count);
            count = 0;
        }
        pthread_mutex_unlock(&evmutex);


    }
}


void *func2()
{
    while(1)
    {
        pthread_mutex_lock(&evmutex);
        count++;
        if(count == N)
        {
            pthread_cond_signal(&evcond);
        }
        pthread_mutex_unlock(&evmutex);


    }
}

int main ()
{
    pthread_t ptd1,ptd2;

    pthread_mutex_init(&evmutex,NULL);
    pthread_cond_init(&evcond,NULL);
    count = 0;
    pthread_create(&ptd1,NULL,func1,NULL);
    pthread_create(&ptd2,NULL,func2,NULL);


    pthread_exit(NULL);
    pthread_mutex_destroy(&evmutex);
    pthread_cond_destroy(&evcond);

    return 0;
}
alk
  • 69,737
  • 10
  • 105
  • 255
Shashwat Kumar
  • 5,159
  • 2
  • 30
  • 66

2 Answers2

1

You've not synchronized with the producer, func2(), and telling it to wait until the consumer, func1(), has processed the condition.

Nothing stops the producer from signalling the condition, re-acquiring the mutex, and incrementing the counter again. pthread_cond_signal doesn't mean your producer will halt and wait for the consumer to process. This means the producer might increment the counter many times before your consumer gets scheduled and wakes up to print the current number.

You'd need to add another condition variable which the producer waits for after it's incremented the counter to N, and have the consumer signal that when it has processed the counter.

In addition to that, you need to handle spurious wakeups as other answers mentions.

nos
  • 223,662
  • 58
  • 417
  • 506
  • You could also use a barrier rather than a second condition variable for the second synchronisation point. – caf Feb 11 '13 at 09:18
0

Some implementations of pthread_cond_wait() suffer from spurious wake-ups, and because of this, it's common practice to use a while (cond) { pthread_cond_wait(...); } loop to work around this.

I found a good explanation of the problem and causes here: Why does pthread_cond_wait have spurious wakeups?

Community
  • 1
  • 1