下面起了两个线程,每个对一个全局变量加500次,不假思索进行回答,会认为最后这个全局变量的值会是1000,然而事实并不是这样:
#include<iostream> #include <process.h> #include <windows.h> using namespace std; typedef unsigned int (_stdcall *PThreadFunc)(void*); int g_nCount = 0; unsigned int _stdcall ThreadTest1(void*) { for (int i = 0; i < 500; i++) { g_nCount++; } return 0; } unsigned int _stdcall ThreadTest2(void*) { for (int i = 0; i < 500; i++) { g_nCount++; } return 0; } void main() { g_nCount = 0; HANDLE h1 = (HANDLE)_beginthreadex(NULL, 0, ThreadTest1, NULL, 0, NULL); HANDLE h2 = (HANDLE)_beginthreadex(NULL, 0, ThreadTest2, NULL, 0, NULL); HANDLE hs[2] = {h1, h2}; WaitForMultipleObjects(2, hs, TRUE, INFINITE); CloseHandle(h1); CloseHandle(h2);
printf("Global count:%d\n", g_nCount); getchar();
}
然而运行多次、每次结果都不同,而且,几乎不会等于1000:
造成这种现象的原因很简单,就是g_nCount在进行自增的时候没有实现原子操作,g_nCount的本质其实是:
- Interlocked函数
为了保证自增的原子性,改为使用Interlocked函数:
#include<iostream> #include <process.h> #include <windows.h> using namespace std; typedef unsigned int (_stdcall *PThreadFunc)(void*); int g_nCount = 0; unsigned int _stdcall ThreadTest1(void*) { for (int i = 0; i < 500; i++) { //Sleep(12); //g_nCount ++; InterlockedIncrement((volatile unsigned long long*)&g_nCount); } return 0; } unsigned int _stdcall ThreadTest2(void*) { for (int i = 0; i < 500; i++) { //Sleep(10); //g_nCount ++; InterlockedIncrement((volatile unsigned long long*)&g_nCount); } return 0; } void main() { g_nCount = 0; HANDLE h1 = (HANDLE)_beginthreadex(NULL, 0, ThreadTest1, NULL, 0, NULL); HANDLE h2 = (HANDLE)_beginthreadex(NULL, 0, ThreadTest2, NULL, 0, NULL); HANDLE hs[2] = { h1, h2 }; WaitForMultipleObjects(2, hs, TRUE, INFINITE); CloseHandle(h1); CloseHandle(h2); printf("Global count:%d\n", g_nCount); getchar(); }
这样就保证了自增的原子性。