Discussion on POSIX Cond and Windows synchronization object event

Source: Internet
Author: User
One reason: Recently, when implementing a thread pool, we need to use the cond and mutex in POSIX to wait and synchronize threads. This function is similar to the synchronization object event of Ms. It is found that the use of Cond and mutex is still quite unfriendly. To be honest, Ms has done quite well in synchronizing object APIs, and the documentation is also very clear. Anyway, since POSIX can only be used, it can only be done. In the implementation of this thread pool, I encountered the following two problems: 1. There are n threads waiting for an event. When a task is added, one of the threads needs to be triggered to start. 2. When the thread pool exits, I Need To trigger all threads to start and detect the exit sign to exit the thread loop. This problem is actually more complex than it seems at the beginning. Next we will analyze the implementation on Windows. First we will introduce the event synchronization object, handle createevent (
Lpsecurity_attributes Lpeventattributes, // Pointer to security attributes
Bool Bmanualreset, // Flag for manual-Reset event
Bool Binitialstate, // Flag for initial state
Lpctstr Lpname// Pointer to event-Object Name
);
The second parameter: bmanualreset indicates whether the object is a manual or automatic variable. We will focus on this. This value determines the following features:
  • When the event is a manual variable, once triggered, it remains in the trigger state and calls the resetevent reset state. If this value is triggered, all threads that call the waitxxx function should not be blocked on this event.
  • When the event is an automatic variable, once triggered, if a thread is waiting, only one of the threads will be started (only one thread will be started, because the value is reset after a thread is started ). If no thread is waiting, the value remains in the trigger state.
From the introduction of event above, automatic variables trigger a thread at a time, while manual variables remain in the trigger state. However, the system does not say what the wait thread will do if a thread quickly setevent and resetevent. Let's take a look at how to solve the above problem on the MS Platform: The most common method is: 1 create an auto event, this event is used to trigger the worker thread to obtain Task 2 from the task queue to create a manual event. This event is used to trigger all worker threads to exit and then use waitformultiobject to wait for the two events. Problem solved !! 3. The biggest problem in Linux's implementation is that there is no function like waitformultiobject, so we can only create a struct containing mutex and cond to act as event. Because there are two functions triggered by cond, features:
  • Pthread_cond_signal: ensure that only one thread can return when multiple threads call pthread_cond_wait.
  • Pthread_cond_broadcast: ensures that multiple threads can return data while waiting.
When we use cond to implement type triggering and waiting, the code is often as follows: Void wake (allthreads ?) { Mutex lock Set condition = 1; If (allthreads) Pthread_cond_broadcast // triggers all threads Else Pthread_cond_signal // triggers a single thread Mutex unlock } Void wait () { Mutex lock While (condition! = 1) { Pthread_cond_wait (Cond, & mutex); // The wait of Cond needs to input a mutex as the parameter. The wait function will unlock the mutex internally. } Mutex unlock }Why do we need a while loop to check whether the condition is met during wait? There are two main reasons:
  • Cond mechanism. If there is no thread in wait when cond is triggered (either signal or broadcast), the thread will not be able to capture this trigger in the future. This is quite different from Windows event. If the event of the automatic variable is triggered, even if there is no thread waiting at the time, it can also be returned if there is a thread waiting in the future. POSIX cond does not implement this function. Therefore, we can only add condition for judgment. If the condition is 1, you do not need to wait.
  • Pthread_cond_wait may be returned because of the signal. In this case, conditon is not satisfied. Therefore, a while loop is also required.
Based on the above basic knowledge, we have met the following requirements:
  • Cond_signal can trigger only one thread.
  • Cond_broadcast can trigger all threads.
But the problem arises, because there is only one condition. When will it be set to zero? Two conditions must be met:
  • For triggering a single thread, because there is only one start, after it is started, you need to set condtion to zero, indicating that you have consumed this condition.
  • For all started threads, the conditon must be set to zero only when the last thread exits and waits, indicating that everyone has consumed this condition.
The solution is to use the waiter count. The modified code is as follows: Void wake (allthreads ?) { Mutex lock If (condtion =-1 | condition = 1) // Why is such a judgment required? { Mutex unlock Return; } If (allthreads) { Set condition =-1; // indicates waiting for multiple Pthread_cond_broadcast // triggers all threads } Else { Set condition = 1; Pthread_cond_signal // triggers a single thread } Mutex unlock } Void wait () { Mutex lock ++ Waiters; While (condition = 0) { Pthread_cond_wait (Cond, & mutex); // The wait of Cond needs to input a mutex as the parameter. The wait function will unlock the mutex internally. } If (-- waiters = 0) Condition = 0; Mutex unlock }We can explain various cases:
  • No problem if only one thread is triggered. This is the simplest.
  • To trigger multiple threads, if a new thread calls wait after being triggered and before all the old waiting threads are returned, it will not be blocked.
What is the code in red in front of the wake function? It is afraid that the caller calls the wake (true) first, and immediately calls the wake (false), resulting in confusion of the condtion value. By judging whether condition has been triggered, we can avoid problems. 4: Conclusion POSIX Cond and mutex are used in combination, resulting in a loss of efficiency. Since cond_wait still needs to compete for mutex after return, the wait function is executed in serial mode in the user space. I don't know how Windows event is implemented? The above code should not be perfect. If you have any questions, modify it. Do you know what is wrong?
Related Article

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.