师弟问了个非常有趣的多线程问题,之前没有关注,这里写下自己的心得。
对于如下代码:
#include <windows.h> #include <PROCESS.H> #include <STDIO.H> UINT WINAPI Fun1Proc(LPVOID lpParameter); UINT WINAPI Fun2Proc(LPVOID lpParameter); int index1=0; int index2=0; void main() { ULONG hThread1; ULONG hThread2; hThread1 = _beginthreadex(NULL, 0, Fun1Proc, NULL, 0, NULL); hThread2 = _beginthreadex(NULL, 0, Fun2Proc, NULL, 0, NULL); getchar(); CloseHandle((HANDLE)hThread1); CloseHandle((HANDLE)hThread2); } UINT WINAPI Fun1Proc(LPVOID lpParameter) { while(index1++<100) { printf("thread1-%d\n", index1); } return 0; } UINT WINAPI Fun2Proc(LPVOID lpParameter) { while(index2++<100) { printf("thread2-%d\n", index2); } return 0; }
thread1-1 thread1-2 thread1-3 thread1-4 thread2-1 thread2-2 thread2-3 thread1-5 thread1-6 thread2-4 thread2-5 thread2-6 ...但是实际输出为:
thread1-1 thread1-2 thread2-1 thread1-3 thread2-2 thread1-4 thread2-3 thread1-5 thread2-4 thread1-6 thread2-5 ... thread1-99 thread2-98 thread1-100 thread2-99 thread2-100如果不是看这段程序,这种 严格的交替输出都要让我们以为在程序中我们已经做了线程同步了。
仔细思考,许多地方使用类似的程序做多线程切片不可依赖的演示。这里这样的结果考虑可能是系统调度算法做了调整或CPU多核的问题,对于CPU多核的问题测试不是这个原因,那么剩下的就是CPU调度算法的问题了,这里考虑两个线程计算量一样,所以交替输出,我们人为调整其中一个的线程计算量。
如下:
UINT WINAPI Fun1Proc(LPVOID lpParameter) { int i=0; while(index1++<100) { for (i=0; i<100000;i++); printf("thread1-%d\n", index1); } return 0; } UINT WINAPI Fun2Proc(LPVOID lpParameter) { while(index2++<100) { printf("thread2-%d\n", index2); } return 0; }
可以多运行几次程序,好多结果是不一样的,取其中一次结果如下:
thread2-1 thread2-2 thread2-3 thread2-4 thread1-1 thread2-5 thread2-6 thread2-7 thread1-2 thread2-8 thread2-9 thread2-10 thread2-11 thread1-3 ...
其实说这么多,这个演示程序无非就是为了说明一个问题,不能依赖CPU切片来完成线程同步或者说CPU切片是不可控的。
要完成线程同步,必须使用线程同步量,下面使用互斥量完成交替输出:
#include <windows.h> #include <PROCESS.H> #include <STDIO.H> UINT WINAPI Fun1Proc(LPVOID lpParameter); UINT WINAPI Fun2Proc(LPVOID lpParameter); int index1=0; int index2=0; HANDLE hMutex; void main() { ULONG hThread1; ULONG hThread2; hMutex = CreateMutex(NULL, FALSE, NULL); hThread1 = _beginthreadex(NULL, 0, Fun1Proc, NULL, 0, NULL); hThread2 = _beginthreadex(NULL, 0, Fun2Proc, NULL, 0, NULL); getchar(); CloseHandle((HANDLE)hThread1); CloseHandle((HANDLE)hThread2); } UINT WINAPI Fun1Proc(LPVOID lpParameter) { int i=0; while(index1++<100) { WaitForSingleObject(hMutex, INFINITE); for (i=0; i<100000;i++); printf("thread1-%d\n", index1); ReleaseMutex(hMutex); } return 0; } UINT WINAPI Fun2Proc(LPVOID lpParameter) { while(index2++<100) { WaitForSingleObject(hMutex, INFINITE); printf("thread2-%d\n", index2); ReleaseMutex(hMutex); } return 0; }
原创,转载请注明来自http://blog.csdn.net/wenzhou1219