0

I'm learning how to use thread in C, I have created a program which invokes two threads and prints something at the same time.

Here is my code:

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

pthread_mutex_t count_mutex     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  condition_var   = PTHREAD_COND_INITIALIZER;

void *functionCount1();
void *functionCount2();
int  count = 0;

#define COUNT_DONE  10

int main()
{
   pthread_t thread1, thread2;

   pthread_create( &thread1, NULL, &functionCount1, &count);
   pthread_create( &thread2, NULL, &functionCount2, &count);

   pthread_join( thread1, NULL);
   pthread_join( thread2, NULL);

   printf("Final count: %d\n", count);

   exit(0);
}

//Print count when count is even
void *functionCount1()
{

        for(;;)
        {
                pthread_mutex_lock( &count_mutex );


                pthread_cond_wait( &condition_var, &count_mutex );
                        count++;
                        printf("Counter value functionEven: %d\n",count);

                pthread_mutex_unlock( &count_mutex );
        }
}

//Print count when count is odd
void *functionCount2(void *arg)
{
        for(;;)
        {
                pthread_mutex_lock( &count_mutex );
                        if(count%2 == 0)
                        {
                        pthread_cond_signal( &condition_var );
                        }
                        if(count % 2 != 0)
                        {
                        count++;
                        printf("Counter value functionOdd: %d\n",count);
                        }
                        pthread_mutex_unlock( &count_mutex );
                        if(count >= COUNT_DONE) return(NULL);
        }
}

Here is the output I got: enter image description here

The output is correct, but the thread seems like still running on the background. How can I fix that issue and terminating the thread correctly?

Allen Li
  • 479
  • 1
  • 5
  • 11
  • There is no exit from the `functionCount1` function. It will loop forever. In your case stuck on condition variable because `functionCount2` finished execution. Replace `for(;;)` with `while (count < COUNT_DONE)` in `functionCount1`. – Tarek Dakhran Mar 08 '20 at 20:54
  • @TarekDakhran Thanks for your reply, I tried to replace the for loop with while loop, but it still does not work. – Allen Li Mar 08 '20 at 21:06
  • 1
    try `while (count + 1< COUNT_DONE)`, seems like edge case logic is incorrect. `while (count < COUNT_DONE)` also works, but you will have to signal condition variable one more time. – Tarek Dakhran Mar 08 '20 at 21:11
  • It's correct now thanks for your help – Allen Li Mar 08 '20 at 21:15
  • I've edited the comment above. Please reread. – Tarek Dakhran Mar 08 '20 at 21:16

2 Answers2

3

functionCount1 have no condition to terminate the loop. It will wait for condition variable to be signaled after functionCount2 termination forever.

N-A
  • 76
  • 3
  • I have added condition for the ```functionCount1``` with while loop, but it still does not terminate. – Allen Li Mar 08 '20 at 21:08
  • Still, `functionCount2` terminates and `pthread_cond_wait` will wait forever. Consider using `pthread_cond_timedwait`. Are you sure you need condition variable here? You've already had used mutex for locking. – N-A Mar 08 '20 at 21:19
2

Besides that , condition waits are subject to spurious wake ups as well, you must test the predicate (if its indeed true) after waking up and go back to wait if that is not true. Most UNIX system will will unblock this cond wait call, in case signal is delivered to the process and they wont restart the call, you have to handle that in your code.

More on that here

//Print count when count is even
 void *functionCount1()
 {

     for (;;) {
         pthread_mutex_lock(&count_mutex);

         pthread_cond_wait(&condition_var, &count_mutex);
         if(count >= COUNT_DONE)
             return NULL;
         count++;
         printf("Counter value functionEven: %d\n", count);

         pthread_mutex_unlock(&count_mutex);
     }
 }

 //Print count when count is odd
 void *functionCount2(void *arg)
 {
     for (;;) {
         pthread_mutex_lock(&count_mutex);
         if (count % 2 == 0) {
             pthread_cond_signal(&condition_var);
         }
         if (count % 2 != 0) {
             count++;
             printf("Counter value functionOdd: %d\n", count);
         }
         if (count >= COUNT_DONE) {
             pthread_cond_signal(&condition_var);
             pthread_mutex_unlock(&count_mutex);
             return NULL;
         }
         pthread_mutex_unlock(&count_mutex);
     }
 }

The code can be more better expressed but hope that conveys the info that you need .This also needs to add the test for predicate which i did not include.

while(!(predicate == true)) pthread_cond_wait(...);

Piyush Singh
  • 153
  • 7