Second kill multithreading Article 6 typical thread synchronization event

Source: Internet
Author: User

Before reading this article, we recommend that you read the following companion articles:

Second kill multithreading article 4 a typical multi-thread synchronization problem

Second kill multi-thread Article 5 key segment of typical thread synchronization CS

 

In the previous article, key segments are used to solve the classic multi-thread synchronization mutex problem. Due to the "thread ownership" feature of the key segments, the key segments can only be used for thread mutex but not synchronization. This article describes how to use event to solve the thread synchronization problem.

First, we will introduce how to use events. Event is actually a kernel object, which is very convenient to use. Some common functions are listed below.

 

The first createevent

Function: Create an event

Function prototype:

Handlecreateevent (

Lpsecurity_attributeslpeventattributes,

Boolbmanualreset,

Boolbinitialstate,

Lpctstrlpname

);

Function Description:

The first parameter indicates security control. Generally, null is input directly.

The second parameter determines whether the event is set manually or automatically. "True" indicates that the event is set manually, and "false" indicates that the event is set automatically. If it is set to automatic, after waitforsingleobject () is called for this event, resetevent () is automatically called to make the event not trigger. For example, the manual placement event is equivalent to the classroom door. Once the classroom door is opened (triggered), anyone can enter until the teacher closes the classroom door (the event becomes not triggered ). The Automatic Location event is equivalent to the room door for Xray shooting in the hospital. Only one person can access the door after the door is opened. This person will close the door after going in, others cannot enter unless the door is re-opened (the event is re-triggered ).

The third parameter indicates the initial state of the event, and the trur parameter indicates that the event has been triggered.

The fourth parameter indicates the event name, and the input null parameter indicates the anonymous event.

 

Second openevent

Function: Obtain an event handle by name.

Function prototype:

Handleopenevent (

Dworddwdesiredaccess,

Boolbinherithandle,

Lpctstrlpname // name

);

Function Description:

The first parameter indicates the access permission, and event_all_access is generally input to the event. For more information, see the msdn documentation.

The second parameter indicates that the event handle is inherited. Generally, you can pass in "true.

The third parameter indicates the name. Each thread in different processes can access the same event by name.

 

Third setevent

Function: triggers an event.

Function prototype: boolsetevent (handlehevent );

Function Description: after each trigger, one or more threads in the waiting state will become schedulable.

 

Fourth resetevent

Function: sets the event as the last trigger.

Function prototype: boolresetevent (handlehevent );

 

Cleaning and destruction of the last event

Because the event is a kernel object, you can use closehandle () to complete cleaning and destruction.

 

Set an event and a key segment in the typical multithreading problem. Use events to process synchronization between the main thread and sub-thread, and use key segments to process mutual exclusion between sub-threads. For details, see the code:

# Include <stdio. h> # include <process. h> # include <windows. h> long g_nnum; unsigned int _ stdcall fun (void * ppm); const int thread_num = 10; // event and key segment handle g_hthreadevent; critical_section g_csthreadcode; int main () {printf ("classic thread synchronization event \ n"); printf ("-- by morewindows (http://blog.csdn.net/MoreWindows) -- \ n "); // The initialization event and key segment are automatically set. The initial untriggered anonymous event g_hthreadevent = createevent (null, false, false, null); initializecriticalsection (& g_csthreadcode ); handle handle [thread_num]; g_nnum = 0; int I = 0; while (I <thread_num) {handle [I] = (handle) _ beginthreadex (null, 0, fun, & I, 0, null); waitforsingleobject (g_hthreadevent, infinite); // wait for the event to be triggered I ++;} waitformultipleobjects (thread_num, handle, true, infinite ); // destroy the event and key segment closehandle (g_hthreadevent); deletecriticalsection (& g_csthreadcode); Return 0;} unsigned int _ stdcall fun (void * ppm) {int nthreadnum = * (int *) ppm; setevent (g_hthreadevent); // trigger event sleep (50); // some work shoshould to doentercriticalsection (& g_csthreadcode ); g_nnum ++; sleep (0); // some work shoshould to doprintf ("the thread number is % d. The global resource value is % d \ n", nthreadnum, g_nnum ); leavecriticalsection (& g_csthreadcode); Return 0 ;}

The running result is as follows:

It can be seen that the synchronization problem of the classic thread has been successfully solved-the output of the thread number is not repeated, indicating that the main thread and the Child thread have been synchronized. The global resource output increases progressively, indicating that each sub-thread has mutually exclusive access and output to the global resource.

 

Now we know how to use events, but we should study them in depth. Moreover, Microsoft also provides pulseevent () functions for events, so we will continue to dig deeper into Event Events, let's see if there is any other secret.

Let's take a look at the original form of this function:

Fifth pulseevent

Function: Set the event to not triggered immediately after the event is triggered, which is equivalent to triggering an event pulse.

Function prototype: boolpulseevent (handlehevent );

Function Description: This is an uncommon event function. This function is equivalent to calling resetevent () immediately after setevent (). In this case, it can be divided into two types:

1. for manual location events, all offline tasks that are in the waiting state become schedulable.

2. for automatic slot events, only one thread in the waiting state becomes schedulable.

Subsequent events are triggered at the end. This function is unstable because it cannot predict which threads are waiting when pulseevent () is called.

 

The following is an example of triggering an event pulse pulseevent (). The main thread starts seven subthreads, five of which are sleep (10) after a wait function (called a fast thread) is called for an event, another two threads sleep (100) Call the wait function (called a slow thread) for the event ). The main thread starts all the sub-threads and then sleep (50) to ensure that five fast threads are waiting. At this time, if the main thread triggers an event pulse, the five threads will be successfully executed for manual placement events. For automatic slot events, one of these five threads is successfully executed. Regardless of the manual or automatic location event, the two slow threads will miss the event pulse because of sleep (100). Therefore, the slow threads will enter the waiting state and cannot be executed smoothly.

The Code is as follows:

// Use the pluseevent () function # include <stdio. h> # include <conio. h> # include <process. h> # include <windows. h> handle g_hthreadevent; // fast thread unsigned int _ stdcall fastthreadfun (void * ppm) {sleep (10 ); // use this to ensure that the order in which each thread calls the wait function is random. printf ("% s start \ n", (pstr) ppm); waitforsingleobject (g_hthreadevent, infinite ); printf ("% s wait until the event is triggered successfully \ n", (pstr) ppm); Return 0;} // slow thread unsigned int _ stdcall slowthreadfun (void * ppm) {sleep (100); printf ("% s start \ n", (pstr) ppm); waitforsingleobject (g_hthreadevent, infinite ); printf ("% s wait until the event is triggered successfully \ n", (pstr) ppm); Return 0;} int main () {printf ("use pluseevent () function \ n "); printf (" -- by morewindows (http://blog.csdn.net/MoreWindows) -- \ n "); bool bmanualreset = false; // create the second parameter of the event to manually set true, automatic slot falseg_hthreadevent = createevent (null, bmanualreset, false, null); If (bmanualreset = true) printf ("currently used manual slot event \ n "); elseprintf ("currently using auto-location event \ n"); char szfastthreadname [5] [30] = {"Fast thread 1000", "Fast thread 1001 ", "Fast thread 1002", "Fast thread 1003", "Fast thread 1004"}; char szslowthreadname [2] [30] = {"Slow thread 196 ", "Slow thread 197"}; int I; for (I = 0; I <5; I ++) _ beginthreadex (null, 0, fastthreadfun, szfastthreadname [I], 0, null); for (I = 0; I <2; I ++) _ beginthreadex (null, 0, slowthreadfun, szslowthreadname [I], 0, null ); sleep (50); // ensure that all the fast threads have started printf ("Now the main thread triggers an event pulse-pulseevent () \ n"); pulseevent (g_hthreadevent ); // calling pulseevent () is equivalent to calling the following two sentences at the same time // setevent (g_hthreadevent); // resetevent (g_hthreadevent); sleep (3000); printf ("time, main thread stops running \ n "); closehandle (g_hthreadevent); Return 0 ;}

The running result of the Automatic Location event is as follows:

For manual location events, the running result is as follows:

 

 

Summary event

1. Events are kernel objects, which are dividedManual location eventAndAutomatic Location event. The event contains a count (all kernel objects), a Boolean value indicating whether to manually set a bit event or automatically set a bit event, and a Boolean value indicating whether the event is triggered.

2. events can be triggered by setevent (), which is set by resetevent () as not triggered. You can also use pulseevent () to send an event pulse.

3. events can solve the problem of synchronization between threads, so they can also solve the problem of mutual exclusion.

 

The next two articles, second kill multithreading, seventh classic thread synchronization mutex, and second kill multithreading, eighth classic thread synchronization semaphores semaphore will introduce how to use mutex and semaphores to solve this classic thread synchronization problems. You are welcome to continue the second kill multi-thread journey.

 

Reprinted please indicate the source, original address: http://blog.csdn.net/morewindows/article/details/7445233

If this article is helpful to you, click "TOP" to support it. Your support is the greatest motivation for my writing. Thank you.

 

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.