Search code examples
clinuxcondition-variable

Condition variable unlocking in linux c


This is some code I created just to test some stuff about condition variables and mutexes in general. It's just supposed to count to 10, but for some reason the worker threads keep getting stopped on the printlock mutex, because the main thread is not waking up when it waits on printcond. This is my output:

"I have this many threads: 7
This is my 1 time running, and my number is 0!
This is my 2 time running, and my number is 1!"

I must be missing something pretty obvious about condition variables. I have tried unlocking printlock in the worker thread after signalling printcond, and that makes the code run, but then the main thread only prints the last value to get to it. I want the main thread to print "The number I got" for all 1-10. How do I do that? I cannot understand the logical structure of this stuff and I have looked everywhere for a solution. Any help is appreciated.

pthread_mutex_t varlock;
pthread_mutex_t printlock;
pthread_cond_t printcond;

void *worker(void *args)
{
int * count = args;
int run = 1;
while(1==1)
{
    pthread_mutex_lock(&varlock);
    if(*count == 10)
    {
        pthread_mutex_unlock(&varlock);
        printf("I am a thread exiting\n");
        return NULL;
    }
    else
    {
        printf("This is my %d time running, and my number is %d!\n", run, *count);
        pthread_mutex_lock(&printlock);
        pthread_cond_signal(&printcond);
        *count = *count +1;
        run++;
    }
    pthread_mutex_unlock(&varlock);
}
}

int main(int argc, char **argv)
{
int num = 7;
printf("I have this many threads: %d\n", num);
int * count = malloc(sizeof(int));
*count = 0;
if (pthread_mutex_init(&varlock, NULL) != 0)
{
    printf("mmult: Failed initializing mutex\n");
    return 1;
}
if (pthread_mutex_init(&printlock, NULL) != 0)
{
    printf("mmult: Failed initializing mutex\n");
    return 1;
}
pthread_mutex_lock(&printlock);
int err=pthread_cond_init(&printcond, NULL);
//Create the threads
pthread_t tid[num];
int i;
for(i = 0; i < num; i++)
{
    err = pthread_create(&(tid[i]),NULL,worker, count);
    if(err)
    {
        perror("mmult: Failed creating thread\n");
        return 1;
    }
}
while(1==1)
{
    if(*count == 10)
    {
        break;
    }
    pthread_cond_wait(&printcond, &printlock);
    printf("The number I got is %d.\n", *count);
    pthread_mutex_unlock(&printlock);
}
//Join all the threads
int status;
for(i = 0; i < num; i++)
{
    pthread_join(tid[i],(void **)&status);
}
printf("Now that I have finished, the count is %d.\n", *count);
return 0;
}

Solution

  • You have a lot of bugs, but the most obvious one is that your second while(1==1) loop unlocks the mutex but does not lock it. So if you do loop, you'll unlock a mutex that's already unlocked. That's a bug.

    Your first while(1==1) loop is also buggy. You unlock the mutex only to immediately lock it again. What purpose do you think that serves?