Windows via C/C ++ learning notes -- "thread synchronization" of kernel objects and "mutex kernel objects"

Source: Internet
Author: User

The mutex Kernel Object ensures that a thread exclusively accesses resources.

The behavior characteristics of mutex kernel objects are similar to those of key code segments, but they are kernel objects, and key code segments are user mode objects, as a result, the mutually exclusive kernel objects run at a lower speed than key code segments. Therefore, when considering the thread synchronization problem, first consider the user mode object.

However, mutex kernel objects can be used across processes. To synchronize threads between multiple processes, you can use mutex kernel objects. At this point, key code segments are powerless.

 

Inside the mutex kernel object, there are some important data:

1. Count: indicates the number of times the mutex kernel object is opened.

2. Thread ID

3. Recursive counter

The thread ID indicates the thread that owns the mutex kernel object, and the recursive counter indicates the number of times that the thread (with mutex object) owns the mutex object.

 

The usage rules of mutex objects are as follows:

  • If the internal thread ID is 0 (or an invalid thread ID), the mutex kernel object is not owned by any thread and a notification is sent, that is, the object is in the "notified" status.
  • If the thread ID is not 0 but a valid thread ID, the mutex kernel object is owned by this thread and the mutex kernel object is in the "not notified" state.
  • Unlike other kernel objects, mutex kernel objects have special code in the operating system and can be used with abnormal rules.

To use a mutex kernel object, you must first create it:

Handle createmutex (
Psecurity_attributes PSA, // Security Attribute
Bool binitialowner, // whether the mutex object is owned by the thread that calls the function at the beginning
Pctstr pszname); // name of the mutex Kernel Object

 

Windows Vista also provides a function to create a mutually exclusive kernel object:

Handle createmutexex (
Psecurity_attributes PSA, // Security Attribute
Pctstr pszname, // name of the mutex Kernel Object
DWORD dwflags, // whether the mutex object is owned by the thread that calls the Function
DWORD dwdesiredaccess); // access restriction

If the binitialowner parameter of the 1st functions is true, the created mutex kernel object is owned by the thread that calls the function at the beginning, and Its thread ID is set to the thread ID, the recursive counter is set to 1.

If false is passed to this parameter, the thread ID and recursive counter of the mutex kernel object are set to 0, indicating that the mutex kernel object is not owned by any thread, the mutex kernel object is in the "notified" status.

The meaning of the dwflags of the 2nd functions is the same as that of the binitialowner parameter of the 1st functions. 0 is like false. create_mutex_initial_owner is equivalent to true.

The two functions are successful, and the handle of the mutex kernel object is returned. If the two functions fail, null is returned.

 

You can use the "name" to open a created mutex kernel object:

Handle openmutex (
DWORD dwdesiredaccess, // access restriction
Bool binherithandle, // whether to allow the returned handle to be inherited by the quilt Process
Pctstr pszname); // name

 

After creating a mutex Kernel Object and obtaining its handle, it can protect resources.

In a thread (represented by T below), before you need to access resources, you can call the "Wait function" to pass the mutex object (represented by m below) handle of the waiting function. Inside the waiting function, check the thread ID of m through the handle. If the value is not 0, it indicates that M is in the "not notified" status, thread t enters the waiting state (with exceptions, as described below ). At this time, the system will remember this situation. When M is released by other threads and Its thread ID is set to 0 again, the system will wait for a thread (such as t) on it) set the thread ID of M, and set the recursive counter of m to 1, allowing the thread (such as t) to enter the schedulable state.

Note: The comparison and setting of the thread ID of the mutex object are both in the form of "atom", so the mutex kernel object is "thread safe.

 

The exception is described below. This means that the mutex kernel object can be used with abnormal rules. That is, when a mutex kernel object is in the "not notified" state, a thread waiting on it may continue to run.

For example, there is a mutex kernel object m in the "not notified" status, and a thread t (id x ). T calls the wait function to wait for M. In this case, t usually enters the wait state. However, if the system checks that the t id is the same as the M thread ID, the thread does not enter the waiting state, but remains in the schedulable state. After the thread successfully waits for the mutex kernel object, add 1 to the recursive counter of the mutex kernel object m.

That is to say, if the recursive counter of a mutex kernel object is greater than 1, the thread must wait for the same mutex Kernel Object multiple times.

 

Once the current thread successfully waits for a mutex kernel object, the thread can exclusively occupy some resources to access these shared resources. Other threads that attempt to access these resources wait for the same mutex object to enter the waiting state.

If the current thread ends its access to the resource, it must release the mutex Kernel Object and use the releasemutex function:

Bool releasemutex (handle hmutex); // The parameter is a mutually exclusive kernel object handle.

 

This function reduces the recursive count of mutex kernel objects by 1. If a thread successfully waits for a mutually exclusive Kernel Object multiple times, it must call the releasemutex function the same number of times to reduce its recursive count, when the recursive count of the mutex kernel object is reduced to 0, its thread ID is set to 0 and enters the "notified" state.
When the mutex kernel object enters the "notified" state, the system checks whether there are threads waiting for it. If yes, it selects one of the threads based on the principle of fairness, set the thread ID of the mutex kernel object to the thread ID of the selected thread, and set the recursive count of the mutex object to 1.

 

Based on the description above, we can conclude that the mutex kernel object is different from other kernel objects, that is, it has a "thread ownership" concept, which makes the mutex kernel object special.

When a thread calls the releasemutex function to release a mutex object, the system checks whether the thread ID of the mutex object is the same as the thread ID of the thread. If the thread ID is the same, the recursive count of the mutex object is reduced by 1; otherwise, if releasemutex does not work, false is returned.

Another phenomenon is called "Mutual Exclusion objects are discarded ".

Assume that a mutex kernel object is owned by a thread, but this thread is terminated for some special reasons, such as calling the exitthread or terminatethread function, however, this mutex object is not released before termination. At this time, the system can track the thread kernel objects with mutex kernel objects. The system knows that this mutex object is discarded by a thread and sets the thread ID of the mutex object to 0, set the recursive count to 0. Then, the system checks whether other threads are waiting for this mutex object. If yes, it selects one fairly and sets the thread ID of the mutex object to the thread ID of the selected thread, this is the same as previously discussed. The difference is that the value returned by the wait function is wait_abandoned rather than wait_object_0. In this case, it is inappropriate to access resources because you do not know the status of the resources.

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.