/*
對兩個線程進行輪流操作。
一個線程輸出1-100
第二個線程輸出101-200
結果:1
101
2
102
。。。。。。。
*/
#include "stdafx.h" #include <Windows.h> DWORD WINAPI Thread1(LPVOID lParam) { for (int i = 1; i <= 100; ++i) { _tprintf(TEXT("Thread1=%d\n"), i); } return 0; } DWORD WINAPI Thread2(LPVOID lParam) { for (int j = 101; j <= 200; ++j) { _tprintf(TEXT("Thread2=%d\n"), j); } return 0; } int _tmain(int argc, _TCHAR* argv[]) { HANDLE hThead[2]; hThead[0] = CreateThread(nullptr, 0, Thread1, NULL, 0, nullptr); //Sleep(1); hThead[1] = CreateThread(nullptr, 0, Thread2, NULL, 0, nullptr); WaitForMultipleObjects(sizeof(hThead)/sizeof(HANDLE), hThead, TRUE, INFINITE); getchar(); return 0; }
第一種情況:
可以看出,以上的操作只是普通的輸出,而且是按1-200輸出。
第二種情況:
hThead[0] = CreateThread(nullptr, 0, Thread1, NULL, 0, nullptr);
Sleep(1);
hThead[1] = CreateThread(nullptr, 0, Thread2, NULL, 0, nullptr);
在線程1后停留1ms,發現:又出現兩個結果:
第一:如第一種情況,按順序輸出。
第二:線程只輸出,可能是33或80(不確定位置),再完整地輸出線程2,再輸出線程1.
那么第二種情況,為什么會出現兩個不同的結果?
原因:
重點:當遇到阻塞,當前線程會休眠。又因為CPU永在搶棧式工作,所以CPU隨機運行進程中的線程。
當線程1占用CPU時間到了,就會返回主線程。運行Sleep(),這時就出現了阻塞,CPU會隨機地選擇
其中一條線程進行運行。
第三情況:
在每一個線程輸出后,再Sleep(),使當前線程休眠,轉到其他線程。
如:
_tprintf(TEXT("Thread1=%d\n"), i);
Sleep(1);
結果發現:線程1輸出1,線程2輸出101、102,線程1輸出2.。。。
可以看到線程1和線程2雖然是錯開輸出的,但不是我們所要的。
改善方法:
改進:利用信號,對指定的線程進行操作。
#include "stdafx.h" #include <Windows.h> //標志號 enum{ No1, No2, }; DWORD g_dwNum = 0; DWORD WINAPI Thread1(LPVOID lParam) { for (int i = 1; i <= 100; ++i) { while (g_dwNum != No1) { Sleep(1); } _tprintf(TEXT("Thread1=%d\n"), i); g_dwNum = No2; } return 0; } DWORD WINAPI Thread2(LPVOID lParam) { for (int j = 101; j <= 200; ++j) { while (g_dwNum != No2) { Sleep(1); } _tprintf(TEXT("Thread2=%d\n"), j); g_dwNum = No1; } return 0; } int _tmain(int argc, _TCHAR* argv[]) { HANDLE hThead[2]; g_dwNum = No1; hThead[0] = CreateThread(nullptr, 0, Thread1, NULL, 0, nullptr); //Sleep(1); hThead[1] = CreateThread(nullptr, 0, Thread2, NULL, 0, nullptr); //等待所有子線程結束 WaitForMultipleObjects(sizeof(hThead)/sizeof(HANDLE), hThead, TRUE, INFINITE); getchar(); return 0; }
注意:此處while (g_dwNum != No1),為什么不用if?
如果使用了if無法確保g_dwNum一定發生翻轉,經驗證,有些時候不會出現輪流輸出。