Mutex of C ++ Multithreading

Source: Internet
Author: User

Multi-threaded threads synchronize mutex (the function is the same as that of the criticalsection, which ensures that only one thread can access Shared resources at a certain time point, but is a kernel object. Therefore, the access speed is slower than that of the criticalsection, however, the wait time-out function is added. You can select one of them based on the actual situation)

One mutex
The mutex Kernel Object ensures that the thread has mutex access to a single resource. In fact, mutex objects are named accordingly. A mutex object contains a quantity, a thread ID, and a recursive counter.
The behavior of the mutex object is the same as that of the key code segment, but the mutex object belongs to the kernel object, and the key code segment belongs to the user mode object. This means that mutex objects run slowly than key code segments. However, this also means that multiple threads in different processes can access a single mutex object, and this means that a timeout value can be set when the thread is waiting to access the resource.

ID is used to identify which thread in the system has a mutex object. Recursive counters are used to specify the number of times that the thread has a mutex object.
Mutex objects have many purposes and are one of the most common kernel objects. Generally, they are used to protect memory blocks accessed by multiple threads. If multiple threads need to access the memory block at the same time, the data in the memory block may be damaged. The mutex object can ensure that any thread accessing the memory block has exclusive access to the memory block, thus ensuring data integrity.

The rules for using mutex objects are as follows:

• If the thread ID is 0 (this is an invalid ID), the mutex object is not owned by any thread and sends a notification to this mutex object.

• If the ID is a non-zero number, a thread has a mutex object and does not send a notification to the mutex object.

• Unlike all other kernel objects, mutex objects have special code in the operating system, allowing them to violate normal rules.

To use a mutex object, a process must first call createmutex to create a mutex object:
Handlecreatemutex (
Psecurity_attributes PSA,
Bool finitialowner,
Pctstr pszname );
The initialowner parameter is used to control the initial State of a mutex object. If false is passed (this is the value normally passed), the ID and recursive counter of the mutex are set to 0. This means that the mutex object is not owned by any thread, so it must be notified.
If the finitialowner parameter is set to true, the thread ID of the object is set to the ID of the calling thread, and the recursive counter is set to 1. Because the ID is a non-zero number, no notification is sent when the mutex object starts.

By calling a wait function and passing a handle to the mutex object that protects the resource, the thread can gain access to the shared resource. Internally, wait for the function to check the thread ID to see if it is 0 (the mutex object sends a notification signal ). If the thread ID is 0, the thread ID is set to the ID of the calling thread, the recursive counter is set to 1, and the calling thread remains schedulable.

If the wait function finds that the ID is not 0 (the notification signal of the mutex object is not sent), The Calling thread enters the waiting state. The system will remember this situation and set the thread ID to the ID of the waiting thread and the recursive counter to 1 when the ID of the mutex object is reset to 0, and allow the waiting thread to become a schedulable thread again. As in all cases, checks and modifications to mutually exclusive kernel objects are performed through atomic operations.

Once the thread successfully waits for a mutex object, the thread will know that it has exclusive access to protected resources. Any other thread that tries to access the resource (by waiting for the same mutex object) is put in the waiting state. When a thread having access to resources no longer needs access, it must call the releasemutex function to release the mutex:
Bool releasemutex (handle hmutex );
This function reduces the recursive counter of an object by 1.

When this object changes to the notified State, the system needs to check whether any thread is waiting for the mutex object. If yes, the system selects one of the waiting threads Based on the fairness principle and grants it the ownership of the mutex object. Of course, this means that thread I D is set to the ID of the selected thread and the recursive counter is set to 1. If no other thread is waiting for the mutex object, the mutex object remains notified. In this way, the mutex object can be obtained immediately after the next thread of the mutex object.

API 2

Mutex Function Description
Createmutex Creates or opens a named or unnamed mutex object.
Createmutexex Creates or opens a named or unnamed mutex object and returns a handle to the object.
Openmutex Opens an existing named mutex object.
Releasemutex Releases ownership of the specified mutex object.

Three instances
Example from msdn: There is a loop in the thread function. mutex is obtained at the beginning of each loop, and global or static operations are performed, which is equivalent to operations in key code segments, then release it after use. You can execute it and view the result.

# Include <windows. h>
# Include <stdio. h>
# Define threadcount 64 // less than 64
Handle ghmutex;
Int G_x = 0;
DWORD winapi writetodatabase (lpvoid );
Void main ()
{
Handle athread [threadcount];
DWORD threadid;
Int I;
// Create a mutex with no initial owner
Ghmutex = createmutex (
Null, // default security attributes
False, // initially not owned
Null); // unnamed mutex

If (ghmutex = NULL)
{
Printf ("createmutex error: % d/N", getlasterror ());
Return;
}
// Create worker threads

For (I = 0; I <threadcount; I ++)
{
Athread [I] = createthread (
Null, // default security attributes
0, // default stack size
(Lpthread_start_routine) writetodatabase,
Null, // no thread function arguments
0, // default creation flags
& Threadid); // receive thread identifier

If (athread [I] = NULL)
{
Printf ("createthread error: % d/N", getlasterror ());
Return;
}
}
// Wait for all threads to terminate

Waitformultipleobjects (threadcount, athread, true, infinite );
// Close thread and mutex handles
For (I = 0; I <threadcount; I ++)
Closehandle (athread [I]);
Closehandle (ghmutex );
Printf ("G_x is: % d/N", G_x );
}
DWORD winapi writetodatabase (lpvoid lpparam)
{
DWORD dwcount = 0, dwwaitresult;
// Request ownership of mutex.

While (dwcount <100)
{
Dwwaitresult = waitforsingleobject (
Ghmutex, // handle to mutex
Infinite); // no time-out interval
 
Switch (dwwaitresult)
{
// The thread got ownership of the mutex
Case wait_object_0:
_ Try {
G_x ++;
// Todo: Write to the database
Printf ("thread % d writing to database/N ",
Getcurrentthreadid ());
Dwcount ++;
}
_ Finally {
// Release ownership of the mutex object
If (! Releasemutex (ghmutex ))
{
// Deal with error.
}
}
Break;
// The thread got ownership of an abandoned mutex
Case wait_abandoned:
Return false;
}
}
Return true;
}
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.