Second kill multithreading Article 5 key section of typical thread synchronization CS

Source: Internet
Author: User

In the previous article "second kill multi-thread fourth, a typical multi-thread synchronization problem", a classic multi-thread synchronization mutex problem is proposed. This article will use the key section critical_section to try to solve this problem.

This article first introduces how to use the key segments, and then analyzes the implementation mechanism and principle of the key segments in depth.

The key section critical_section contains a total of four functions, which are very convenient to use. The following is a prototype and usage of the four functions.

 

Function: initialization

Function prototype:

Void initializecriticalsection (maid section );

Function Description: initialization is required after key segment variables are defined.

 

Function: Destroy

Function prototype:

Void deletecriticalsection (maid section );

Function Description: destroy the function after it is used up.

 

Function: Enter key areas

Function prototype:

Void entercriticalsection (maid section );

Function Description: The system ensures that threads are mutually exclusive to key areas.

 

Function: off-switch key area

Function prototype:

Void leavecriticalsection (maid section );

 

Then, set two key areas in the typical multithreading problem. One is when the main thread increments the sub-thread program number, and the other is when the sub-threads are mutually exclusive to access and output global resources. 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; // key segment variable declaration critical_section g_csthreadparameter, g_csthreadcode; int main () {printf ("classic thread synchronization key segment \ n"); printf ("-- by morewindows (http://blog.csdn.net/MoreWindows) -- \ n "); // initialize the iterator (& g_csthreadparameter); initializecriticalsection (& g_csthreadcode); handle [thread_num]; g_nnum = 0; int I = 0; while (I <thread_num) {entercriticalsection (& g_csthreadparameter); // enter the key area of the Child Program number. Handle [I] = (handle) _ beginthreadex (null, 0, fun, & I, 0, null ); ++ I;} waitformultipleobjects (thread_num, handle, true, infinite); deletecriticalsection (& g_csthreadcode); deletecriticalsection (& g_csthreadparameter); Return 0 ;} unsigned int _ stdcall fun (void * ppm) {int nthreadnum = * (int *) ppm; leavecriticalsection (& g_csthreadparameter ); // exit the sleep (50) in the key area of the subthread program number; // some work shoshould to doentercriticalsection (& g_csthreadcode); // enter the mutually exclusive area of each subthread g_nnum ++; sleep (0); // some work shoshould to doprintf ("thread number: % d Global Resource Value: % d \ n", nthreadnum, g_nnum); leavecriticalsection (& g_csthreadcode ); // return 0 when leaving the mutually exclusive regions of each sub-thread ;}

The running result is as follows:

It can be seen that each sub-thread can access and output Global Resources mutex, but the synchronization between the main thread and the sub-thread is still a bit problematic.

Why?

To solve this problem, the most direct method is to first add a breakpoint in the program to view the program's running process. The breakpoint disposal diagram is as follows:

Then press F5 for debugging. Normally, the two breakpoints should be executed in turn, but this is not the case during actual debugging. The main thread can pass the first breakpoint multiple times

Entercriticalsection (& g_csthreadparameter); // enter the key area of the Child Program number

This statement. This indicates that the main thread can enter this key area multiple times! Find out the reason why the main thread and sub-thread cannot be synchronized. Let's analyze the cause. ^_^

 

Find the definition of the key section critical_section, which is defined as rtl_critical_section in WINBASE. h. Rtl_critical_section declares in winnt. H that it is actually a struct:

Typedef struct _ rtl_critical_section {

Prtl_critical_section_debugdebuginfo;

Longlockcount;

Longrecursioncount;

Handleowningthread; // from the thread's clientid-> uniquethread

Handlelocksemaphore;

Dwordspincount;

} Rtl_critical_section, * prtl_critical_section;

The parameters are described as follows:

First parameter: prtl_critical_section_debugdebuginfo;

For debugging.

 

The second parameter: longlockcount;

The initialization is-1, and N indicates that n threads are waiting.

 

The third parameter: longrecursioncount;

Indicates the number of times that the owner thread of the key segment obtains the key segment for this resource. The initial value is 0.

 

Fourth parameter: handleowningthread;

That is, the thread handle that owns the key segment. Microsoft comments it as -- From the thread's clientid-> uniquethread

 

Fifth parameter: handlelocksemaphore;

It is actually an auto-Reset event.

 

Sixth parameter: dwordspincount;

Rotation lock settings, ignored under a single CPU

 

From this structure, we can know that the key segment will record the thread handle that owns the key segment, that isThe key section has the concept of "thread ownership ".. In fact, it will use the fourth parameter owningthread to record the thread handle authorized to enter the key area. If this thread enters again, entercriticalsection () the third parameter recursioncount is updated to record the number of times that the thread enters and returns immediately to let the thread enter. When other threads call entercriticalsection (), it is switched to the waiting state. Once a thread with the thread ownership calls leavecriticalsection (), the number of times it enters is 0, the system automatically updates the key segment and switches the waiting thread back to the schedulable status.

Therefore, you can compare the key section to the hotel room card. You can call entercriticalsection () to apply for a room card. After you get the room card, you can naturally access the room multiple times. When you call leavecriticalsection () no one else can access the room before handing over the room card.

Back to this typical thread synchronization problem, the main thread is precisely because of the "thread ownership", that is, the House card, therefore, it can repeat the key code area, causing the subthread to modify this parameter before receiving the parameter. SoKey segments can be used for mutual exclusion between threads, but cannot be used for synchronization.

 

In addition, the overhead of switching the thread to the waiting state is large. To improve the performance of the key segment, Microsoft merges the rotation lock into the key segment, so that entercriticalsection () the thread will be switched to the waiting state only after a rotating lock is continuously loop. The following is the initialization function of the key segment with the rotation lock.

Function: initializes key segments and sets the number of rotations.

Function prototype:

Boolinitializecriticalsectionandspincount (

Lpcritical_sectionlpcriticalsection,

Dworddwspincount );

Function Description: Generally, the number of rotations is set to 4000.

 

Function: modifies the number of rotations of key segments.

Function prototype:

Dwordsetcriticalsectionspincount (

Lpcritical_sectionlpcriticalsection,

Dworddwspincount );

 

In chapter 8 of the fifth edition of Windows core programming, we recommend that you use the rotation lock when using key segments, which helps improve performance. It is worth noting that if the host has only one processor, setting the rotation lock is invalid. Threads that cannot enter the key area are always switched to the waiting state by the system.

 

 

Summary of the following key sections:

1. The key segments are initialized, destroyed, accessed, and removed from the key areas.

2. The key segment can solve the thread mutex problem, but it cannot solve the synchronization problem because it has "thread ownership.

3. We recommend that you use the key segment with the rotation lock.

 

The next article "second kill multithreading Article 6" typical thread synchronization event "describes how to use Event Events to solve this typical thread synchronization problem.

 

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

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.