Introduction to several Windows Thread Synchronization Methods

Source: Internet
Author: User

All threads in the system need to access system resources. One thread occupies a certain resource, and other threads that need this resource cannot complete their own tasks; for example, if a thread is reading data from a certain memory and another thread is modifying the value of this memory, this is not what we want, so there must be a set of rules between threads, otherwise it will be messy. Communication is required between threads. For example, if thread a occupies the resource x required by a thread B, thread B can only wait or be suspended during the period of thread a's occupation. When thread a runs out of resource X, the system will tell thread B that resource X can be used, or it will wake up thread B in the suspended state, and then thread B will gain control over resource X, other threads that want to use resource X have to experience what B has just encountered. When multiple threads need a resource at the same time, they must comply with the following two rules:

1: multiple threads access resources at the same time, and the resource integrity cannot be damaged.

2: one thread needs to notify other threads that a task has been completed.

Atomic access: interlocked functions.Multi-threaded programming is mostly related to atomic access, that is, when a thread accesses a resource, it ensures that no other thread can access the resource.

The structure of the incremental function interlockedexchangeadd is as follows:

Interlockedexchangeadd (

Unsigned long volatile * addend, // address of the incremental variable

Unsigned long value // increment Value

)

Volatile indicates that data is read in the memory every time, instead of reading data from the cache. For example, a global variable is modified in a multi-threaded function, and in a multi-core CPU, this variable may have copies in the cache of multiple CPUs. If volatile modification is not required, the CPU may not read data in the memory due to optimization, instead, it reads data directly from the cache. In this case, it is likely that this value has been modified, so that the CPU does not read the latest data,ProgramAn error will certainly occur. After you use volatile to modify this variable, all the high-speed caches of this variable will become invalid, so this problem will not occur. Volatile plays a very large role in multi-threaded programming and has the highest efficiency. But he can only modify a single variable.Code.

Interlockedexchangeadd can be executed very quickly. It only takes several CPU cycles. Using interlockedexchangeadd to modify the value of a variable seems to be a little useless, because volatile is enough, simple and fast. But interlockedexchange is very useful when implementing the rotation lock. The rotation lock code is roughly as follows:

 Bool Sourceisuse = False  ;  Void  Fun (){  //  Wait until the resource is available             While (Interlockedexchange (& sourceisuse, True ) = True  ) {Sleep (  0  );}  //  Resource Access Operations  ......  //  When resources are used up, open the lock to allow other resources to be accessed Interlockedexchange (& sourceisuse, False  );} 

 

Interlockedexchange: change the value of the first parameter to the value of the second parameter, and return the original value of the first parameter. When the first thread came, it passed the while loop smoothly and got locked. As a result, while was always true, and later the thread kept spinning in while, after the current thread is used up, it will open the lock, and then the new thread can jump out of the while loop and lock (keep locking when waiting), unlocking exclusive resources, the new thread is waiting again. Like the revolving door at the front door of the building, after a group of people enter, the people behind the building can only wait outside. After the people inside the building go out, the people behind the building can also go in and go back and forth.

 

High-speed cache row. When the CPU reads a byte from the memory, it does not really read only one byte, but reads a high-speed cache row, A high-speed cache row may be 32 bytes, 64 bytes, or 128 bytes. The number of bytes it reads is an integer multiple of 32, so that the CPU does not need to read the memory frequently, so as to improve the performance of the program, when the CPU accesses a memory, it will access the memory next to the memory, the probability is very large, so it will be read together. For more information about data alignment, see myArticle《Data Alignment.

 

Advanced Thread Synchronization. I just briefly talked about the rotation lock. Now I am talking about the bad rotation lock. The problem with the rotation lock is that the waiting thread has been executing a useless dead loop, A waste of CPU time is definitely intolerable, although it was once tolerated. When a thread needs a certain resource and the resource is occupied by another thread, if the thread waits for a while and cannot obtain the resource, the thread should be switched to the waiting state, let the system act as the proxy for this thread. When this resource can be used, the system will wake up the thread and then the thread can exclusively occupy this resource. The key section is to implement this function.

 

Key Section. The key segment is a small piece of code. Before execution, you need to exclusively access some shared resources. In this way, multiple lines of code can be accessed in an atomic manner, when one thread accesses this Code, other threads can only wait. The steps for using the key Section are as follows:

Critical_section g_cs; // construct a critical_section instance.

Initializecriticalsection (& g_cs); // initialize members of g_cs

Entercriticalsection (& g_cs); // enter the key section

Leavecriticalsection (& g_cs); // exit the key section

Deletecriticalsection (& g_cs); // clear g_cs

Entercriticalsection checks the member variables of the critical_section structure. These members indicate whether a thread is accessing the resource and which thread is accessing the resource. entercriticalsection will perform some tests. If no thread is accessing the resource, entercriticalsection updates the variable member to indicate that a thread is accessing the resource and returns the code from entercriticalsection to continue executing the code in the key section, if the variable member indicates that a thread is already accessing the resource, entercriticalsection will use an event kernel object to switch the thread to the waiting state. The waiting state thread will not waste the CPU time, the system will remember that this thread wants to use this resource. Once the current thread calls leavecriticalsection, the system will automatically update the member variable of critical_section and switch the waiting thread to the schedulable state.

Leavecriticalsection checks the member variables of the critical_section structure and removes the counter by one. If the counter changes to 0, leavecriticalsection updates the member variables, indicating that no threads are currently accessing resources. If there is a waiting thread, switches the waiting thread to the schedulable state.

 

When a thread enters a key segment, if a thread is accessing the key segment, the system switches the new thread to the waiting state, this means that the thread is switched from user mode to kernel mode. The overhead of this switch is about 1000 CPU cycles. This overhead is actually very large, so the rotation lock is used inside entercriticalsection, instead of switching the thread to the wait state immediately, we first use the rotation lock to test whether the thread has released access to the resource. If yes, the new thread does not need to be switched to the waiting state, so it can directly access the resource. That is to say, it takes time to round the rotation lock. If the rotation lock is polling for a period of time, the thread still does not release resources. Sorry, the system will not let it continue polling, because the system does not know how long it will take to poll. After all, the polling will always consume CPU time, and the system will stop polling, switches a new thread to the waiting state. When a resource is released to access the resource, the system switches the new thread to the schedulable state.

 

Silm read/write lock. The purpose of srwlock is the same as that of the key segment. It is to protect resources and prevent other threads from accessing them. The difference is that it distinguishes whether a thread is a read thread or a write thread. We all know that a resource can be read by multiple threads at the same time, that is, it cannot be read or read at the same time. That is to say, the write operation must be exclusive, and the read operation can be shared.

The function called by the read/write lock is similar to the key segment.

Rtl_srwlock lock;

Initializesrwlock (& lock );

Acquiresrwlockexclusive (& lock); // exclusive access

Releasesrwlockexclusive (& lock );

Acquiresrwlockshared (& lock); // shared access

Releasesrwlockshared (& lock );

Windows Thread Basics

Introduction to Windows kernel objects

Author:Chen taihan

Blog:Http://www.cnblogs.com/hlxs/

 

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.