For the sake of convenience and code succinctness, we can only output the final report result to see if the program is running incorrectly. This is also very similar to counting how many users log in a website every day. Each user login is simulated with one thread, and the thread runs with a variable that represents the count. The value of the program's last output count indicates how many users are logged in today. If this value is not equal to the number of threads we started, it obviously shows that the program is problematic. The entire program code is as follows: [cpp] view plain copy #include #include #include Volatilelong g_nLoginCount; //login times Unsigned int __stdcall Fun(void *pPM); //thread function Constint THREAD_NUM = 10; //Number of threads started Unsigned int __stdcall ThreadFun(void *pPM) { Sleep(100); //some work should to do g_nLoginCount++; Sleep(50); Return 0; } Int main() { g_nLoginCount = 0; HANDLE handle[THREAD_NUM]; For (int i = 0; i < THREAD_NUM; i++) Handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, NULL, 0, NULL); WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); Printf ("%d users log in and the result is %d", THREAD_NUM, g_nLoginCount); Return 0; } The program simulates 10 user logins, and the program will output the result: As with the previous thread-reporting program, the results of the program output seem to be fine. Below we add some users to try, now simulate 50 users to log in, in order to facilitate the observation, in the program, the 50 user login process is repeated 20 times, the code is as follows: [cpp] view plain copy #include #include Volatilelong g_nLoginCount; //login times Unsigned int __stdcall Fun(void *pPM); //thread function constDWORD THREAD_NUM = 50; / / start the number of threads DWORD WINAPI ThreadFun(void *pPM) { Sleep(100); //some work should to do g_nLoginCount++; Sleep(50); Return 0; } Int main() { Printf("Atomic Operation Interlocked Series Function Usage"); Printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --"); / / Repeat 20 times to observe the conflict caused by multi-threaded access to the same resource Int num= 20; While (num--) { g_nLoginCount = 0; Int i; HANDLE handle[THREAD_NUM]; For (i = 0; i < THREAD_NUM; i++) Handle[i] = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL); WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); Printf ("%d users log in and the result is %d", THREAD_NUM, g_nLoginCount); } Return 0; } The results of the operation are as follows: Now that the results are out, it is clear that 50 threads have executed g_nLoginCount++; the operation, but the output is indeterminate, it may be 50, but it may be less than 50. To solve this problem, we will analyze the g_nLoginCount++; operation. In the VC6.0 compiler on g_nLoginCount++; this statement breakpoint, press F5 to enter the debug state, and then press the Disassembly button on the Debug toolbar, so that the assembly code window appears. It can be found that a simple self-increment statement in the C/C++ language is actually composed of three pieces of assembly code, as shown in the following figure. Explain the meaning of these three pieces of assembly: The first assembly reads the value of g_nLoginCount from memory into register eax. The second assembly adds the value in register eax to 1 and the result is still stored in register eax. The third assembly writes the value in register eax back into memory. Thus, due to the concurrency of thread execution, it is very likely that when thread A executes to the second sentence, thread B starts executing, and thread B writes the original value to register eax again, so that the value calculated by thread A is modified by thread B. It is. In this way, the result is unpredictable - 50 may appear, possibly less than 50. Therefore, when reading and writing a variable in a multi-threaded environment, we need a way to ensure that the increment operation on a value is an atomic operation—that is, it cannot be interrupted. When a thread performs an atomic operation, other threads must wait. It can only begin to perform the atomic operation after it has completed. This kind of hardware-related operation will not be complicated. Fortunately, the Windows system provides us with some functions that start with Interlocked to accomplish this task (these functions are called Interlocked series functions below). Here are some common Interlocked family functions: 1. Increase or decrease operation LONG__cdeclInterlockedIncrement(LONG volatile* Addend); LONG__cdeclInterlockedDecrement(LONG volatile* Addend); Returns the value after the variable has been incremented or decremented. LONG__cdec InterlockedExchangeAdd(LONG volatile* Addend, LONGValue); Return the value after the operation, pay attention! Adding a negative number is minus. 2. Assignment operation LONG__cdeclInterlockedExchange(LONG volatile* Target, LONGValue); Value is the new value and the function returns the original value. In this case, just use the InterlockedIncrement() function. Change the thread function code to: [cpp] view plain copy DWORD WINAPI ThreadFun(void *pPM) { Sleep(100);//some work should to do //g_nLoginCount++; InterlockedIncrement((LPLONG)&g_nLoginCount); Sleep(50); Return 0; } Run it again and you can see that the results will be unique. Therefore, in a multi-threaded environment, we should think carefully about the self-increase and decrement of variables, and prevent data access errors caused by multiple threads. BIOTEPT NEMA Rolled steel standard high starting torque, high slip ratio three-phase asynchronous motors B design have insulation class F, Protection grade IP44, service factor 1.15. Voltage rating of 230/460V. The rated frequency is 60HZ. Premium Efficiency Motor,Nema Premium Efficiency, Ie4 Electric Motors,A 3 Phase Induction Motor Ningbo Biote Mechanical Electrical Co.,Ltd , https://www.biotept.com