[Windows] thread mantalk-slim read/write lock for Thread Synchronization

Source: Internet
Author: User

This series is intended to record the knowledge points of windwos threads, including thread basics, thread scheduling, thread synchronization, TLS, and thread pool.

 

Slim read/write lock

Srwlock protects a resource with the same purpose as the key segment, and constructs an atomic accessCodeTo prevent other threads from accessing it. However, unlike the key segment, srwlock allows you to distinguish between the thread that wants to read the resource value and the thread that wants to write the resource value, because reading only the resource will not destroy the data, the following is a simple usage of the SLIM read/write lock:

 
Srwlock g_srwlock... // init srwlockinitializesrwlock (& g_srwlock );... // apply for "exclusive lock" acquiresrwlockexclusive (& g_srwlock) when writing resources; // execute the write action... // release "exclusive lock" releasesrwlockexclusive (& g_srwlock) after the write is complete; // apply for "shared lock" acquiresrwlockshared (& g_srwlock) When read is required ); // execute the read operation... // release the "shared lock" releasesrwlockshared (& g_srwlock) after the read is complete; // the system automatically cleans g_srwlock and no other cleanup Functions

We can see that there are two locks used for this mechanism: "exclusive lock" and "shared lock ". Exclusive locks can be returned only when no lock exists; otherwise, they are blocked; shared locks can be returned without exclusive locks, even if there are other shared locks. In this way, the exclusive lock is applied before the write operation, and the shared lock applied before reading can ensure that the shared resource data will not be accidentally damaged. In addition, only the initialization function does not release the function.

It seems that srwlock is more similar to key segments, but srwlock lacks the following two features:

1. The corresponding tryenterxxx function does not exist. If the lock is occupied, you can only choose to block the calling thread;

2. srwlock cannot be obtained recursively. That is to say, a thread cannot lock resources multiple times to write resources multiple times. The key segment can be used. In retrospect, because the key segment will judge whether the current thread is a resource-sharing occupation during the enter process, if so, it will "allow" and increase the reference count. However, srwlock never cares who the calling thread is.

 

Srwlock matching condition variable

Another useful feature of srwlock is that it can be used with "conditional variables" to complete more complex synchronization tasks. Let's assume the following scenario: there is a shared queue, two server threads are responsible for reading the entries in the queue for processing, and two client threads are responsible for writing the entries in the queue for processing by the service tip thread, when there are no entries in the queue, the server thread should be suspended until an entry enters the queue. On the other hand, when the queue is full, the client thread should be suspended until the server processes at least one entry, to release at least one project.

First, create several shared resource locks. srwlock is the read/write lock mentioned above, and condition_variable is the condition variable here:

Srwlock g_srwlock; condition_variable g_cvreadytoproduce; // The read thread is used to notify the write thread to start writing condition_variable g_cvreadytoconsume; // The write thread is used to notify the read thread to start reading.

Design the following client write thread process:

Acquiresrwlockexclusive (& g_srwlock): Obtain the exclusive lock before writing. If there are other locks, it will be blocked;

Sleepconditionvariablesrw (& g_cvreadtoproduce, & g_srwlock, infinite, 0): When the queue is full, wait for the g_cvreadtoproduce variable signal (this signal should be initiated by the server thread that performs the read operation ). Parameters: & g_srwlock, infinite, and 0 indicate temporarily releasing the g_srwlock and waiting for the variable signal;

Write queue...: write operation on the queue. If the queue passes sleep during the previous step and the g_srwlock is temporarily released, the g_srwlock will be automatically re-obtained in this step;

Releasesrwlockexclusive (& g_srwlock): Release the exclusive lock after writing the queue;

Wakeallconditionvariable (& g_cvreadtoconsume): initiates the g_cvreadtoconsume signal to all server threads waiting for the entries in the queue to notify them to start reading the queue;

 

Design the following server read process:

Acquiresrwlockshared (& g_srwlock): obtains the shared lock before writing. If exclusive lock exists, the lock is blocked;

Sleepconditionvariablesrw (& g_cvreadtoconsume, & g_srwlock, infinite, condition_variable_lockmode_shared): When the queue is empty, wait for the g_cvreadtoconsume variable signal (this signal should be initiated by the client thread for ). Parameters: & g_srwlock, infinite, and condition_variable_lockmode_shared indicate sharing g_srwlock (not released) and waiting for variable signals permanently;

Read queue...: Read operations on the queue;

Releasesrwlockshared (& g_srwlock): Release the shared lock after reading the queue;

Wakeallconditionvariable (& g_cvreadtoproduce): sends a g_cvreadtoproduce signal to all client threads waiting for at least one space entry in the queue, notifying them that they can start writing to the queue;

 

In the above process, we designed a scenario and used srwlock and the so-called conditional variables. The usage of the conditional variables is summarized as follows:

Condition_variable variable; // create Variable Void winapi variable (_ out pcondition_variable conditionvariable); // wait for variable signal bool winapi variable (_ inout pcondition_variable conditionvariable, _ inout psrwlock srwlock, _ in DWORD dwmilliseconds, _ in ulong flags); // send a variable signal to wake up the thread void winapi wakeallconditionvariable (_ inout pcondition_variable conditionvariable) waiting for the variable );

In the previous article, we also mentioned conditional variables when talking about key segments. In fact, conditional variables can also be used in key segments, but the APIs are not the same:

Bool winapi variable (_ inout pcondition_variable conditionvariable, _ inout javascriticalsection, _ in DWORD dwmilliseconds); void winapi variable (_ inout pcondition_variable conditionvariable );

Besides wakeallconditionvariable, there is also a wakeconditionvariable. As the name suggests, the latter only wakes up a thread waiting for a variable, which is similar to "automatic resetting of events ".

For more information about conditional variables, see using condition variables.

Labor fruit, reproduced please indicate the source: http://www.cnblogs.com/P_Chou/archive/2012/06/24/slim-rw-read-in-thread-sync.html

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.