Why do we need a condition check before pthread_cond_wait

后端 未结 2 1586
陌清茗
陌清茗 2020-12-15 06:37

I am trying to learn basics of pthread_cond_wait. In all the usages, I see either

if(cond is false)
   pthread_cond_wait

or



        
相关标签:
2条回答
  • 2020-12-15 07:04

    You must test the condition under the mutex before waiting because signals of the condition variable are not queued (condition variables are not semaphores). That is, if a thread calls pthread_cond_signal() when no threads are blocked in pthread_cond_wait() on that condition variable, then the signal does nothing.

    This means that if you had one thread set the condition:

    pthread_mutex_lock(&m);
    cond = true;
    pthread_cond_signal(&c);
    pthread_mutex_unlock(&m);
    

    and then another thread unconditionally waited:

    pthread_mutex_lock(&m);
    pthread_cond_wait(&c, &m);
    /* cond now true */
    

    this second thread would block forever. This is avoided by having the second thread check for the condition:

    pthread_mutex_lock(&m);
    if (!cond)
        pthread_cond_wait(&c, &m);
    /* cond now true */
    

    Since cond is only modified with the mutex m held, this means that the second thread waits if and only if cond is false.

    The reason a while () loop is used in robust code instead of an if () is because pthread_cond_wait() does not guarantee that it will not wake up spuriously. Using a while () also means that signalling the condition variable is always perfectly safe - "extra" signals don't affect the program's correctness, which means that you can do things like move the signal outside of the locked section of code.

    0 讨论(0)
  • 2020-12-15 07:08

    You need a while loop because the thread that called pthread_cond_wait might wake up even when the condition you are waiting for isn't reached. This phenomenon is called "spurious wakeup".

    This is not a bug, it is the way the conditional variables are implemented.

    This can also be found in man pages:

    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.

    Update regarding the actual code:

    void* proc_add(void *name) 
    {
        struct vars *my_data = (struct vars*)name;
    
        printf("In thread Addition and my id = %d\n",pthread_self());
    
        while(1) {
    
            pthread_mutex_lock(&mutexattr);
    
            while(!my_data->ipt){  // If no input get in
                pthread_cond_wait(&mutexaddr_add,&mutexattr);  // Wait till signalled
            }
    
            my_data->opt = my_data->a + my_data->b;
            my_data->ipt=1;
            pthread_cond_signal(&mutexaddr_opt);
    
            pthread_mutex_unlock(&mutexattr);
    
            if(my_data->end)
                pthread_exit((void *)0);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题