一.如果不加鎖,會怎么樣?
可能會發生數據競爭,造成數據錯亂.
例子:
本來想要的結果n=0,但是執行發現n的值不為0,而且有多種取值.究其原因,是因為多個線程之間會發生數據競爭,導致CPU線程調度時出現問題,不能夠保證線程內執行代碼的原子操作.我發現string str = "hello";這一句是必要的,不然它就不會出現n不為0的現象.(有待進一步研究)
注意,如果要所有子線程執行完畢后,再執行主線程.要有WaitForMultipleObjects操作.
#include "windows.h" #include <iostream>using namespace std;const int ThreadNum = 50; int g_Num = 0; DWORD WINAPI ThreadFun(void * param) { for (int i = 0; i < 100; i++) { g_Num = g_Num+1; string str = "hello"; g_Num = g_Num-1; } return 0; } int main() { DWORD lpThread[ThreadNum]; HANDLE h[ThreadNum]; for (int i = 0; i <ThreadNum; i++) { h[i] = CreateThread(NULL, 0, ThreadFun, NULL, 0, &lpThread[i]); } WaitForMultipleObjects(ThreadNum, h, TRUE, INFINITE); //等待所有的子線程執行完畢. int n = g_Num; cout << "n:" << n << endl; return 0; }
二.加鎖后的情形
WaitForMultipleObjects是必須的,一開始忘記了使用這個,導致在EnterCriticalSection處報錯,猜測是主線程沒有等子線程執行完畢就結束了程序.為了驗證猜想,將WaitForMultipleObjects注釋掉,
在子函數中打印,發現確實是這個原因.
加鎖后每次n打印出來的都是0了.
#include "windows.h" #include <iostream> using namespace std; const int ThreadNum = 50; CRITICAL_SECTION g_Cs; int g_Num = 0; DWORD WINAPI ThreadFun(void * param) { for (int i = 0; i < 100; i++) { EnterCriticalSection(&g_Cs); g_Num = g_Num+1; string str = "hello"; g_Num = g_Num-1; LeaveCriticalSection(&g_Cs); } return 0; } int main() { InitializeCriticalSection(&g_Cs); DWORD lpThread[ThreadNum]; HANDLE h[ThreadNum]; for (int i = 0; i <ThreadNum; i++) { h[i] = CreateThread(NULL, 0, ThreadFun, NULL, 0, &lpThread[i]); } WaitForMultipleObjects(ThreadNum, h, TRUE, INFINITE); //等待所有的子線程執行完畢. int n = g_Num; cout << "n:" << n << endl; DeleteCriticalSection(&g_Cs); return 0; }