Why do pthread_cond_wait always carry a mutex?

Source: Internet
Author: User

Fromhttps://www.zhihu.com/question/24116967?q=linux%20%E5%A4%9A%E7%BA%BF%E7%A8%8B%20%E8%99%9A%E5%81%87%E5%94% A4%e9%86%92%20%e9%97%ae%e9%a2%98%3f%e6%88%91%e6%80%8e%e4%b9%88%e8%a7%a3%e9%87%8a%e4%b8%8d%e5%90%8c%e8%82%af%e5 %ae%9a%e5%93%aa%e9%87%8c%e4%b8%8d%e5%af%b9%e4%ba%86Wuzhijiang, or like to write code at night—————— Update, Errata ——————


Back to the dormitory last night Google to the official documents (in the engine room when Google Hung, how search are not search ...) ), found that the previous explanation has a mistake, that is, the "atom" semantics pointed out by the high school students. I'll add that with the test code I wrote yesterday.

I have this code in the original answer:
    pthread_mutex_unlock(mtx);    pthread_cond_just_wait(cv); pthread_mutex_lock(mtx);
In fact, the above three lines of code are not pthread_cond_wait (CV, MTX) inline expansion. Where the first and second lines must be "atomized", and the third line can be separated (the reason why the third line should be placed inside can be found in the original answer).

So why can't the first and second lines be separated? This is because it is necessary to ensure that: if thread a first enters the wait function (even if it is not in the actual wait state, such as releasing MTX), then you must ensure that the broadcast that the other thread calls after it must be able to wake up thread A.


So, put the code in the original answer again:
Thread A, condition testPthread_mutex_lock(Mtx);A1While(Pass==0){A2Pthread_mutex_unlock(Mtx);A3Pthread_cond_just_wait(cv); //A4 pthread_mutex_lock (mtx//a5}pthread_mutex_unlock (mtx< Span class= "P" >); //thread B, condition changed, corresponding signal code pthread_mutex_lock (); //b1pass = 1//b2pthread_mutex_unlock (mtx) ; //b3pthread_cond_signal (cv//b4               

If the execution sequence is: A1, A2, A3, B1, B2, B3, B4, A4, then thread A will not be awakened. A3 is executed before thread B, which means that the wait function was called before signal, so the assurances mentioned above are not met.

Workaround:
    1. Attaching a thread to the wait queue first
    2. Releasing a mutex
    3. Into the waiting
Interested students can look at the source code (PTHREAD_COND_WAIT.C), attached to the waiting queue this operation is locked, so it can be guaranteed that the previously initiated signal will not be wrong to wake the thread, and then the signal must wake up the thread.

Therefore, the following code is absolutely error-prone:
// 线程A,条件测试pthread_mutex_lock(mtx);        // a1while(pass == 0) {              // a2     pthread_cond_wait(cv, mtx); // a3}pthread_mutex_unlock(mtx);      // a4// 线程B,条件发生修改,对应的signal代码pthread_mutex_lock(mtx);   // b1pass = 1;                  // b2pthread_mutex_unlock(mtx); // b3pthread_cond_signal(cv);   // b4
If thread a runs first, then the execution sequence must be: A1, A2, A3, B1, B2, B3, B4, A4.
If thread B runs first, then the execution sequence might be: B1, B2, B3, B4, a1, A2, A4
May also be: B1, B2, B3, A1, A2, A3, B4, A4

So, if I design the pthread API, then I will add a pthread_cond_unlock_and_wait function, pseudo code as follows:
IntPthread_cond_wait(Cv,Mtx){IntRet=Pthread_cond_unlock_and_wait(Cv,Mtx);Pthread_mutex_lock(Mtx);ReturnRet;}Thread A, condition testPthread_mutex_lock(Mtx);If(Pass==0) pthread_cond_unlock_and_wait ( cvmtx); pthread_mutex_unlock (mtx Thread B, the condition changes, the corresponding signal code pthread_mutex_lock (mtx ); //b1pass = 1//b2pthread_mutex_unlock (mtx) ; //b3pthread_cond_signal (cv//b4               
The advantage of this is that if we can guarantee that there is no spurious wake-up (that is, we do not need the while loop test condition), then we can change the code of thread A to the above form, so that we only need to execute the Pthread_mutex_unlock () function once. The previous version needs to be executed at least two times.


—————— the original answer ——————

Thank you for your answer!
After seeing it, I was inspired to think that it might have something to do with the usual use of conditional variables.

First you need to understand two points:
    • The wait () operation is usually accompanied by condition detection, such as:
      while(pass == 0) pthread_cond_wait(...);
    • The signal* () function is usually accompanied by a condition change, such as:
      pass = 1;pthread_cond_signal(...)
Since both are involved in variable pass, it is necessary to lock the race Condition to prevent it. So the code will turn out like this:
 //condition test pthread_mutex_lock ( mtx); while (pass == 0 ) pthread_cond_wait (...); pthread_mutex_unlock (mtx The condition changes, the corresponding signal code pthread_mutex_lock (mtxpass = 1; Pthread_mutex_unlock (mtx (...);             

Then we assume that the wait () operation does not automatically release and acquire the lock, then the code becomes this:
Condition testPthread_mutex_lock(Mtx);While(Pass==0){pthread_mutex_unlock (mtxpthread_cond_just_wait (cvpthread_mutex_lock (mtx} pthread_mutex_unlock (mtx The condition changes, the corresponding signal code pthread_mutex_lock (mtxpass = 1; Pthread_mutex_unlock (mtx (cv        

Over time, programmers find that the three operations of unlock, just_wait, and lock are always together. A pthread_cond_wait () function is provided to complete the three functions at the same time.

Another evidence is that the signal () function does not need to pass the mutex parameters, so it is more untenable to say that the mutex parameter is used to synchronize the wait () and signal () functions.

So my conclusion is: the mutex passed is not intended to prevent race inside the wait () function condition! Instead, you always get a mutex before calling wait () (for example, a mutex for race condition that solves the pass variable here), and the mutex must be freed before you call Wait (), and must be retrieved after the call to wait ().


Therefore, the pthread_cond_wait () function is not a fine-grained function, but it is a useful function.

Why do pthread_cond_wait always carry a mutex?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.