Conditional variables and spurious wakeup false wake-up in multithreaded programming

Source: Internet
Author: User

1. Overview
The conditional variable (condition variable) is a mechanism for synchronizing threads with shared variables. Typical scenarios include producer-consumer models, thread pool implementations, and so on.
The use of a condition variable consists of two actions:
1) The thread waits for a condition and the condition is true to continue execution, and the condition is false to suspend itself (avoid busy wait, save CPU resources);
2) After the thread has performed some processing, the condition is established, and the thread that waits for the condition is notified to continue execution.
3) in order to prevent race-condition, the condition variable is always used in conjunction with the mutex variable mutex.
General Programming Mode:

C + + code
  1. var mutex;
  2. var cond;
  3. var something;
  4. Thread1: (Waiting for thread)
  5. Lock (mutex);
  6. while (something not true) {
  7. Condition_wait (cond, mutex);
  8. }
  9. Do (something);
  10. Unlock (mutex);
  11. //============================
  12. Thread2: (Unlock thread)
  13. Do (something);
  14. ....
  15. something = true;
  16. Unlock (mutex);
  17. Condition_signal (cond);


Function Description:
(1) Condition_wait (): Called when the front thread goes to sleep immediately, while the mutex mutex unlocks (the two operations are atomic, indivisible) so that other threads can enter the critical section to modify the variable.
(2) Condition_signal (): After the thread calls this function, except that the current thread continues to execute, the operating system does the following actions: One thread wakes from the thread that enters the sleep from condition_wait (), and the thread that is awakened is attempting to lock (lock) Mutex, the thread has successfully returned from condition_wait () when the lock is successfully locked.

2. Function interface

C code
    1. Pthread:pthread_cond_wait/pthread_cond_signal/pthread_cond_broadcast ()
    2. Java:Condition.await ()/condition.signal ()/condition.signalall ()



3. False wakeup (spurious wakeup) when using conditional waits, we use

Java code
    1. while (condition not met) {  
    2.     condition_wait (Cond, mutex);   
    3. }  
    4. instead of:   
    5. If (   Conditions do not meet  ) {  
    6.    condition_wait (Cond,mutex);   
    7. }    



This is because there may be a false wake-up "spurious wakeup" situation.
That is, even if no thread calls Condition_signal, the function that originally called condition_wait may return. At this point the thread is awakened, but the condition is not satisfied, this time if the condition is not checked and down, it may cause the subsequent processing error.
Spurious wakeup can occur in a multiprocessor system on Linux/when the program receives a signal. Also exists on Windows systems and Java virtual machines. False wakeup should be avoided during system design, but this can affect the execution efficiency of the condition variable, and since the error caused by false wakeup can be avoided through the while loop, the logic of the program becomes the case of the while loop.
Note: Even in the case of spurious wakeup, the thread will not return from condition_wait () until the mutex has been successfully locked. Even if there are multiple threads that are being falsely awakened, they can only be executed in the order of one thread of a thread, namely: Lock (Mutex)? Inspection/processing? Condition_wai () or unlock (mutex) to unlock.

4. Unlocking and waiting for transfer (wait morphing)

Unlocking the mutex mutex and emitting a wake-up signal condition_signal is two separate operations, then there is a sequential problem. Who can then produce different results first. As follows:
[Color=red] (1) According to unlock (mutex); Condition_signal () Order, when the waiting thread is awakened, because the mutex has been unlocked, the awakened thread can easily lock the mutex and return from Conditon_wait ().

C code
    1. //...
    2. Unlock (mutex);
    3. Condition_signal (cond);



(2) according to Condition_signal (); Unlock (Mutext) order, when the waiting thread wakes up, it tries to lock the mutex, but if the mutex is not unlocked at this time, the thread goes to sleep again, and after the mutex is successfully unlocked, the thread is awakened again and locks the mutex, from the condition_wait ( ) returns.

C code
    1. //...
    2. Condition_signal (cond);
    3. Unlock (mutex);



[/color]

As you can see, in the Order of (2), the context switch to the waiting thread may occur 2 times, severely impacting performance. So in the later implementations, in the case of (2), if the thread is awakened but cannot lock the mutex, then the thread is transferred (morphing) to the mutex mutex's wait queue, avoiding the overhead of context switching. -- Wait morphing

When programming, it is recommended to use the Order of (1) to unlock and wake-up signals. Java programming can only be in the Order of (2), or an exception occurs!!。

In the Susv3http://en.wikipedia.org/wiki/single_unix_specification specification (pthread), the implementation is the same regardless of which of these two sequences are used.

I've seen Apue. mutexes are used for exclusive access to shared data instead of waiting for primitives, and conditional variables are required if waiting for a condition to occur. When a conditional variable is used to check if a Boolean expression is true, a mutex is required for this check to be secured, so the mutex and the condition variable are joined together for synchronization.

The mutex and condition variables are used as follows:
Pthread_mutex_lock (&lock);
while (Condition_is_false) {
Pthread_cond_wait (&cond, &lock);
}

Can you replace the IF? The answer is no, otherwise it will cause spurious wakeup false awakening. Because not only before pthread_cond_wait to check whether the condition is set up, after pthread_cond_wait also check. Because pthread_cond_wait can be awakened not only by Pthread_cond_signal/pthread_cond_broadcast but also by other signals, the latter is false awakening.

Linux pthread_cond_wait is called with the Futex system, this is a slow system call, see Apue know any slow system call is interrupted by the signal will return 1, and the errno to Eintr, if the slow system call restart function is closed, You need to restart it manually where the system call is called, like this:

while (1) {
int ret = Syscall ();
if (Ret < 0 && errno = = eintr)
Continue
Else
Break
}

But Futex can not use this, because after the end of the Futex to restart the process has a time window, in this window may occur pthread_cond_signal/phread_cond_broadcast, if this happens, then the Pthread _cond_wait when you miss a change in the condition variable, you will wait indefinitely. But what if you don't write like the above and can't restart the Futex system call? This goes back to why you use while instead of if when checking for Boolean conditions.

Using while does not miss the phread_cond_signal/pthread_cond_broadcast because of false wakeup, and detects this wake as false wake-up by judging the while condition is not established and continues to call Futex to continue waiting.

Conditional variables and spurious wakeup false wake-up in multithreaded programming

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.