Simple examples of C ++ multi-thread programming and multi-thread programming
C ++ does not provide any multithreading mechanism, but in windows, we can call the SDK win32 api to Write multi-threaded programs. The following is a brief introduction:
Function used to create a thread
HANDLE CreateThread (
LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId // thread identifier
);
Here we only use the third and fourth parameters, and the third parameter passes the address of a function, which is also the new thread we want to specify, the fourth parameter is the parameter pointer passed to the new thread.
Eg1:
# Include <iostream>
# Include <windows. h>
Using namespace std;
Dword winapi Fun (LPVOID lpParamter)
{
While (1) {cout <"Fun display! "<Endl ;}
}
Int main ()
{
HANDLE hThread = CreateThread (NULL, 0, Fun, NULL, 0, NULL );
CloseHandle (hThread );
While (1) {cout <"main display! "<Endl ;}
Return 0;
}
We can see that the main thread (main function) and our own thread (Fun function) are randomly executed, but the output of the two threads is too fast, which makes it hard to see clearly, we can use functions
VOID Sleep (
DWORD dwMilliseconds // sleep time
);
To pause thread execution, dwMilliseconds indicates 1‰ seconds, so
Sleep (1000 );
1 second suspended
Eg2:
# Include <iostream>
# Include <windows. h>
Using namespace std;
Dword winapi Fun (LPVOID lpParamter)
{
While (1) {cout <"Fun display! "<Endl; Sleep (1000 );}
}
Int main ()
{
HANDLE hThread = CreateThread (NULL, 0, Fun, NULL, 0, NULL );
CloseHandle (hThread );
While (1) {cout <"main display! "<Endl; Sleep (2000 );}
Return 0;
}
Execute the above Code. This time, we can clearly see that Fun display is output on the screen! And main display !, We found that these two functions are indeed run concurrently. careful readers may find that our program outputs a line feed every time the Fun function and main function output content, but we can see that sometimes the program outputs a line break, sometimes it does not output a line break, or sometimes it outputs two lines. What's going on? Next we will change the program to see:
Eg3:
# Include <iostream>
# Include <windows. h>
Using namespace std;
Dword winapi Fun (LPVOID lpParamter)
{
While (1) {cout <"Fun display! \ N "; Sleep (1000 );}
}
Int main ()
{
HANDLE hThread = CreateThread (NULL, 0, Fun, NULL, 0, NULL );
CloseHandle (hThread );
While (1) {cout <"main display! \ N "; Sleep (2000 );}
Return 0;
}
When we run this program again, we find that, as we expected at this time, the content we want to output is correctly output and the format is correct. Next I will explain why our program was not correctly run. Multi-threaded programs run concurrently. If resources are shared among multiple threads, we cannot guarantee that these resources can be used correctly, because resources are not exclusive at this time, for example:
Eg4:
Add a resource int a = 3
There is a thread function selfAdd () which is to make a + =;
Another thread function, selfSub (), is used to make a-=;
Let's assume that the above two threads are waiting for a concurrent job. If selfAdd is executing, we want to program a 6, but at this time selfSub gets the chance to run, so a becomes 0, and after selfAdd reaches the execution opportunity, a + = a, but at this time a is actually 0, not 6 as we expected, let's go back to EG2. Here, we can regard the screen as a resource which is shared by two threads. When the Fun function outputs Fun display! The endl will be output (that is, clearing the buffer and wrapping the line, here we do not need to understand what the buffer is), but at this time the main function is indeed a chance to run, at this time, the Fun function gave the CPU to the main function before it could output a line feed, and the main function is directly in Fun display! And output main display !, As to why sometimes the program outputs two line breaks in a row, the reader can use the same analysis method for analysis. Here I will not talk much about it and leave it to the reader to think for himself.
So why can we run eg2 correctly with eg3? The reason is that multiple threads run concurrently, but some operations must be in one breath and cannot be interrupted. Therefore, we can see that the running results of eg2 and eg3 are different.
So, isn't the eg2 code that we can't let it run correctly? The answer is, of course, whether or not. Next I will explain how to make the eg2 code run correctly. This involves multi-thread synchronization. If a resource is shared by multiple threads, program confusion will occur. Our solution is to allow only one thread to exclusively share the resources. This will solve the above problem.
HANDLE CreateMutex (
LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD
BOOL bInitialOwner, // initial owner
Lptstr lpName // object name
);
This function is used to create an exclusive resource. The first parameter is not used and can be set to NULL. The second parameter specifies whether the resource is initially created by the process, the third parameter specifies the Resource Name.
HANDLE hMutex = CreateMutex (NULL, TRUE, "screen ");
This statement creates a resource named screen and belongs to the process that created it.
BOOL ReleaseMutex (
HANDLE hMutex // handle to mutex
);
This function is used to release an exclusive resource. Once a process releases the resource, the resource will no longer belong to it. If you want to use the resource again, you need to apply for it again. The function for applying for resources is as follows:
DWORD WaitForSingleObject (
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // time-out interval
);
The first parameter specifies the handle of the requested resource, and the second parameter is generally set to INFINITE, indicating that if the requested resource is not applied, it will wait for the resource. If it is set to 0, it indicates that the system will return if no resource is available. You can also specify how long it will wait to return, in the unit of 1‰ seconds. Now, it's time for us to solve the eg2 problem. We can make some modifications to eg2, as shown below:
Eg5:
# Include <iostream>
# Include <windows. h>
Using namespace std;
HANDLE hMutex;
Dword winapi Fun (LPVOID lpParamter)
{
While (1 ){
WaitForSingleObject (hMutex, INFINITE );
Cout <"Fun display! "<Endl;
Sleep (1000 );
ReleaseMutex (hMutex );
}
}
Int main ()
{
HANDLE hThread = CreateThread (NULL, 0, Fun, NULL, 0, NULL );
HMutex = CreateMutex (NULL, FALSE, "screen ");
CloseHandle (hThread );
While (1 ){
WaitForSingleObject (hMutex, INFINITE );
Cout <"main display! "<Endl;
Sleep (2000 );
ReleaseMutex (hMutex );
}
Return 0;
}
Run the code as we expected.
Reprinted from: http://hi.baidu.com/%CF%D0%B5%AD%CA%B0%D2%E4/blog/item/2e56a02f06d89f2e359bf77b.html