Mutex applications for multi-thread synchronization on windows, multi-thread mutex
Mutex application for multi-thread synchronization on windows
- Preface
Thread Composition:
The Zookeeper operating system schedules a certain CPU time for each running thread --Time slice. The system provides a time slice for the thread in a loop mode. The thread runs within its own time, and multiple threads continuously switch and run. Because the time slice is quite short, it gives the user the feeling that, it is as if the thread is running at the same time.
Worker a single cpu computer can run only one thread at a time. If the computer has multiple CPUs, the thread can actually run simultaneously.
On the windows platform, you can use the CreateThread function of the windows api to create a thread. The function declaration is as follows:
WINBASEAPIHANDLEWINAPICreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
Parameter description:
LpThreadAttributes |
Thread security. Use the default security. Generally, the default value is null. |
DwStackSize |
Stack size. 0 indicates the default size. |
LpStartAddress |
The function pointer to be executed by the thread, that is, the entry function. |
LpParameter |
Thread Parameters |
DwCreationFlags |
Thread flag. If it is 0, run immediately after creation |
LpThreadId |
LPDWORD is the return value type. It generally transmits the address to receive the identifier of the thread. It is generally set to null. |
Because windows api functions are used, they include:
#include <windows.h>
In addition, the standard input and output functions are required, so they include:
#include <iostream.h>
-The issue leads to the issue where ticket sales take multiple ticket sales windows as an example. A Global ticket count tickets is defined and two threads are used to sell tickets. The two threads access the same variable tickets, let's first look at an incorrect statement:
// Problematic program # include <windows. h> # include <iostream. h> dword winapi feature (LPVOID lpParameter); dword winapi Fun2Proc (LPVOID lpParameter); int tickets = 100; void main () {HANDLE hThread1; HANDLE hThread2; hThread1 = CreateThread (NULL, 0, Fun1Proc, NULL, 0, NULL); hThread2 = CreateThread (NULL, 0, Fun2Proc, NULL, 0, NULL); CloseHandle (hThread1); CloseHandle (hThread2 ); system ("pause");} dword winapi Fun1Proc (LPVOID lpParameter) {while (TRUE) {if (tickets> 0) {Sleep (1 ); // assume that it is the time cout <"thread1 required ticket:" <tickets -- <endl;} else break;} return 0 ;} dword winapi Fun2Proc (LPVOID lpParameter // thread data) {while (TRUE) {if (tickets> 0) {Sleep (1); cout <"thread2 restart ticket: "<tickets -- <endl;} else break;} return 0 ;}
Sleep (1) in the worker threads; the table name indicates that the thread has no execution permission, and the operating system selects another thread for execution. Therefore, the execution result is:
Execution result
Zookeeper can see that the program is not executed as expected, and the change of tickets is messy. Therefore, when two threads access the same resource, consider
Thread SynchronizationProblem: when one of the threads changes the resource, other threads cannot access the resource. They can only wait until the thread finishes executing the task and other threads can access the resource.
Zookeeper is generally used
Mutex objectTo synchronize threads.
- Mutex object
Features:
A mutex is a kernel object that ensures that a thread has mutex access to a single resource.
The Zookeeper mutex object contains a used quantity, a thread ID, and a counter.
The ID is used to identify which thread in the system has a mutex object. The counter is used to specify the number of times that the thread has a mutex object.
The correct example of using mutex objects for multi-thread synchronization in zookeeper is as follows:
# Include <windows. h> # include <iostream. h> dword winapi Fun1Proc (LPVOID lpParameter // thread data); dword winapi Fun2Proc (LPVOID lpParameter/thread data); int index = 0; int tickets = 100; HANDLE hMutex; void main () {HANDLE hThread1; HANDLE hThread2; hThread1 = CreateThread (NULL, 0, Fun1Proc, NULL, 0, NULL); hThread2 = CreateThread (NULL, 0, Fun2Proc, NULL, 0, NULL); CloseHandle (hThread1); CloseHandle (hThread2); // create an anonymous mutex object with a signal. hMutex = CreateMutex (NULL, FALSE, NULL); system ("pause");} dword winapi Fun1Proc (LPVOID lpParameter // thread data) {while (TRUE) {// wait for the signal of the mutex object, INFINITE indicates that the request has been waiting, and the subsequent code is protected by WaitForSingleObject (hMutex, INFINITE); if (tickets> 0) {Sleep (1); cout <"thread1 skip ticket: "<tickets -- <endl;} else break; // release the ownership of the specified mutex object. The operating system sets the thread id of the mutex object to 0, when the mutex object changes to the notified State, thread 2 can request the mutex object ReleaseMutex (hMutex);} return 0;} dword winapi Fun2Proc (LPVOID lpParameter // thread data) {while (TRUE) {WaitForSingleObject (hMutex, INFINITE); if (tickets> 0) {Sleep (1); cout <"thread2 skip ticket: "<tickets -- <endl;} else break; ReleaseMutex (hMutex);} return 0 ;}
Execution result
Zookeeper tests show that the introduction of the mutex object can solve the problem of resource synchronization between threads. The following questions about mutex objects need to be explained.
- Release of mutex objects
If the main
hMutex=CreateMutex(NULL,TRUE,NULL);
Zookeeper sub-thread:
While (TRUE) {ReleaseMutex (hMutex); // invalid // wait for the signal of the mutex object. INFINITE indicates that it has been waiting and future code is protected by WaitForSingleObject (hMutex, INFINITE );}
Required bytes if the second parameter CreateMutex is true, it indicates that the main thread owns the mutex object. The operating system sets the thread id of the mutex object as the main thread id. If the main thread is not released, then the sub-thread will wait, and the sub-thread has no right to release at this time,Therefore, the principle of using mutex objects is: who owns mutex objects and who releases mutex objects.
In addition, if
hMutex=CreateMutex(NULL,TRUE,NULL);
Merge objects and request mutex again:
WaitForSingleObject(hMutex,INFINITE);
Merge objects and call to release mutex objects at one time:
ReleaseMutex(hMutex);
During this time, the sub-thread is still in the waiting state, and the right to use the mutex object is not obtained because:
Optional values CreateMutex (NULL, TRUE, NULL) because the second parameter is true, the main thread has the right to use the mutex object. The internal counter of the mutex object is added with 1. When WaitForSingleObject is called again to request the mutex object,Internal countersAdd another 1. The counter records the number of times the thread has a mutex object, but only releases ReleaseMutex once. The mutex object is still occupied, so the subthread is not authorized.
Therefore, the correct syntax is as follows:
hMutex=CreateMutex(NULL,TRUE,NULL); WaitForSingleObject(hMutex,INFINITE); ReleaseMutex(hMutex); ReleaseMutex(hMutex);
If you request mutex object multiple times, you should release the mutex object multiple times.
When zookeeper looks at this situation again, the thread does not release the ownership of mutex objects:
DWORD WINAPI Fun1Proc(LPVOID lpParameter) { waitforsingleobject(hmutex,infinite); cout<<"thread1 is running"<<endl; return 0; } DWORD WINAPI Fun2Proc(LPVOID lpParameter) { waitforsingleobject(hmutex,infinite); cout<<"thread2 is running"<<endl; return 0; }
When zookeeper is executed, the following output is still returned:
"thread1 is running "thread2 is running
Zookeeper: If the mutex object is not released when the thread exits, the operating system automatically clears the information of the mutex object occupied by the thread when the thread is destroyed, and the counter returns to zero, in this way, other threads (thread2) can apply for the right to use mutex objects.
- Create a name mutex object
HMutex = CreateMutex (NULL, TRUE, "myApp"); if (hMutex) {if (ERROR_ALREADY_EXISTS = GetLastError ()) {cout <"an identical application is running! "<Endl; return ;}}
A type of application for naming mutex objects in zookeeper is that only one application instance is running by naming mutex objects.
Zookeeper and above are about the use of mutex objects related to multi-thread synchronization on windows platforms.Event objectFor more information, see. If there are any mistakes in this article, I hope you will not be enlightened.
Copyright Disclaimer: This article is the original author applebite. For more information, see the source.