2015년 4월 29일 수요일

The relationship between Condition variable and Mutex

1. pthread API for Condition variable


The pthread's condition variable is used to define specific condition. The pthread_cond_wait function is used to wait for condition and pthread_cond_signal is used to wake up the waiting entity. The definition of two functions are like below.

    int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
    int pthread_cond_signal(pthread_cond_t *cond);

You have to watch the second parameter of pthread_cond_wait carefully. This requires the pointer of mutex. Additionally, you keep in mind that pthread_cond_signal can be ignored if pthread_cond_wait is not executed. So, pthread_cond_signal can wake up only after pthread_cond_wait is executed.

The certain condition seems to have the calculation or comparison, these are changeable due to usage, pthread API does not relate with these part. So pthread uses condition variable in the abstract. You can name just like Condition_A, Condition_B and use them. The real meaning of condition variable will be given when user does programming. So real routine to check the specific condition occurs besides the pthread API.

The flow diagram of waiting condition is like below. First, check the specific condition and if this condition does not meet, we will wait through pthread_cond_wait.

The flow diagram of signalling condition is like below. Some execution causes the condition update. If this can make the specific condition, it will call the pthread_cond_signal.


2. Operation flow analysis in Multi-threads


Now, we will check why mutex is necessary for condition variable. You must consider multi-thread environment, so all threads can run con-currently. We show that condition check and condition update can happen on waiting part and signalling part.
If the condition update happens during the process of condition check at waiting part, this can cause the corruption of shared data and result in wrong operation.

In below diagram, Thread_B in right side runs first. If Thread_A modifies the condition during condition check in Thread_B, Thread_B could not notice this change. And pthread_cond_signal in Thread_A can execute before pthread_cond_wait of Thread_B, Thread_B will not wake up forever.


If we add mutex lock/unlock in both Thread_A and Thread_B to prevent concurrent access, this problem can be resolved. Below diagram shows how to use mutex.


The thread which calls pthread_cond_wait will get into suspend mode, mutex should be
unlocked before thread is suspended. So, pthread_cond_wait is implemented to unlock mutex inside of function. This is the reason why pthread_cond_wait needs the pointer of mutex.

And, the thread which called pthread_cond_wait function will be resumed by pthread_cond_signal. At this moment, the mutex which was unlocked before suspend will be locked again. So you have to remember the post processing (unlock mutex).
The flow diagram of overall processing is like below.


PS. I wrote this post based on my experience of pthread programming. If you have any suggestion, please leave the comment then I will check and update.

댓글 1개:

  1. Hello,
    Very nice tutorial. A small typo is there though.
    int pthread_cond_wait(pthread_cond_t cond, pthread_mutex_t *mutex);

    It shall be

    int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

    I mean the first argument is address of pthread_cond_t variable.

    Regards
    Sumit

    답글삭제