A thread is an execution unit in a process (at least one main thread per process), a process can have multiple threads, and a thread exists only in one process. Belong to a one-to-many relationship on a data relationship. The thread does not occupy system resources, and the resources it uses are all requested by the owning process to the system.
In multiprocessor, different threads can run on different CPUs at the same time, which can improve the efficiency of running the program. In addition, there are times when you have to use multithreading. For example, antivirus software, when killing the virus, it needs to scan the relevant disk files while showing the current scan progress and the problems found. If you put these jobs in one thread, you'll make the program look like it's stuck. In this case, divided into multiple threads, using different threads to accomplish different tasks, you can work together to achieve the desired effect.
APIs used to create threads:
HANDLE CreateThread ( lpsecurity_attributes lpthreadattributes,//indicates the security attribute of the creation thread, a pointer to the security_attributes struct, This parameter is generally set to null size_t dwstacksize,//Specifies the stack size used by the thread, and if NULL, the same as the main thread stack lpthread_start_routine lpstartaddress,// Specifies the thread function, which runs from the entrance of the function, which means that the thread terminates when the function is returned, and that the function belongs to the callback function. /* The thread callback function is defined as follows: DWORD WINAPI ThreadProc ( lpvoid lpparameter); The return value of the function DWORD type, which has only one parameter, This parameter is given by the CreateThread function. The function name of the function can be arbitrarily defined. */ LPVOID lpparameter,//This parameter represents a parameter passed to a thread function, which enables a pointer to any data type, DWORD dwcreationflags,//, indicating the state after the thread was created. The thread can be executed immediately after the thread is created, or the thread can be paused. If immediate execution is required, set to 0, if you want the thread to be in a paused state and set to create_suspened, you will need to call the ResumeThread function when the thread executes. Lpdword lpthreadid//This parameter is used to return the thread ID of the newly created thread);
Try writing a multithreaded example with the following code:
#include <windows.h> #include <iostream>using namespace Std;dword WINAPI threadproc (lpvoid lpparam) {cout << "in ThreadProc" <<endl;return 0;} int main () {HANDLE hthread = CreateThread (null, 0, threadproc,null, 0, NULL);//code insertion at 1cout<< "in main" <<endl; CloseHandle (hthread); return 0;}
The results of operation 1 are as follows:
The results of Operation 2 are as follows:
In the first case, only "in main" was output, and the thread function we specified did not execute the output. This is because the main thread executes the first time slice that the CPU assigns to it, and the main thread finishes executing means the entire program is finished, and the newly created thread does not even have the opportunity to execute.
For this scenario, we can use the following API to make the newly created thread have the opportunity to execute its own thread function.
DWORD WaitForSingleObject ( HANDLE hhandle,//The handle object to wait for DWORD dwmilliseconds//Specifies the number of milliseconds to wait for the timeout, if set to 0, is returned immediately, if set to infinite, it means waiting for the return of the thread function. INFINITE is a system-defined macro that is defined as follows: #define INFINITE 0xFFFFFFFF);
If the function fails, returns wait_failed, returns WAIT_OBJECT_0 if the awaited object becomes fired, or returns wait_timeout if the wait time has ended before the wait object becomes the firing state.
We add the following statement at Code label 1:
WaitForSingleObject (Hthread, INFINITE);
The result of the operation is as follows:
For the second case, it may seem a bit dizzy at first glance, what is the output? In fact, two threads are interleaved when using the output stream buffers. Everyone adds data to the output buffer, so it is best to output the "hybrid" of the two threads to output data, not the data that a thread is going to output, nor the data that the B thread is going to output. What about this situation? Now that you can't use two threads at the same time, let's just use them separately.
You can use a critical section to resolve the problem. The critical section object is a critical_section data structure that the Windows operating system uses to protect critical code to ensure that shared resources under multithreading can be used correctly. At the same time, Windows allows only one thread to enter the critical section.
There are 4 functions for operating the critical section:
Initialize critical section
VOID initializecriticalsection ( lpcritical section lpcriticalsection);
Enter the critical section
VOID entercriticalsection ( lpcritical section lpcriticalsection);
Leave the critical section
VOID leavecriticalsection ( lpcritical section lpcriticalsection);
Delete a critical section
VOID deletecriticalsection ( lpcritical section lpcriticalsection);
The parameters of these 4 APIs are pointers to the critical_section struct.
At this point, we can modify the code to the following form:
#include <windows.h> #include <iostream>using namespace std; Critical_section g_cs;//defines the critical section object DWORD WINAPI ThreadProc (LPVOID lpparam) {entercriticalsection (&G_CS);//Enter the critical section cout << "in ThreadProc" <<endl; LeaveCriticalSection (&g_cs);//Leave the critical section return 0;} int main () {initializecriticalsection (&G_CS); HANDLE hthread = CreateThread (null, 0, threadproc,null, 0, NULL); EnterCriticalSection (&g_cs);cout<< "in main" <<endl; LeaveCriticalSection (&g_cs); WaitForSingleObject (Hthread, INFINITE); CloseHandle (hthread);D eletecriticalsection (&g_cs); return 0;}
At this point the execution results are as follows:
Sometimes, we may create more than one thread for other jobs, how do we reconcile them? The main point is two points: 1. When using public resources, remember to make them mutually exclusive. 2. Ensure that all work is done before exiting the program.
For the 2nd, there is an API that can wait for more than one specified handle:
the DWORD WaitForMultipleObjects (DWORD ncount,//is used to indicate the number of threads that you want the function to wait. This value needs to be between 1 and maximum_wait_objects. CONST HANDLE *lphandles,//The array pointer to the waiting thread handle bool fwaitall,//indicates whether to wait for all threads to complete, and if set to true, waits for all DWORD dwmilliseconds//wait timeout milliseconds, same as in WaitForSingleObject function);
Then, the code outlines for creating multiple threads are as follows:
Define a critical section; DWORD WINAPI threadproc (lpvoid lpparam) { Enter the critical section to perform the desired operation in the shared resource; There may be other operations in the non-critical area from the critical section;} int main () { Initializes a critical section; HANDLE Hthread[n] = {0}; for (int i = 0; i < N; ++i) { Hthread[i] = CreateThread (...);} WaitForMultipleObjects (N, Hthread, TRUE, INFINITE);//Some other operation for (i = 0; i < N; ++i) { CloseHandle (hthread (i));} Delete critical section; return 0;}
Well, the knowledge of multithreading is extensive and profound, it is the first to share here.
On Windows multithreading