线程--时间片
/*
对两个线程进行轮流操作。
一个线程输出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一定发生翻转,经验证,有些时候不会出现轮流输出。