师弟问了个非常有趣的多线程问题,之前没有关注,这里写下自己的心得。
对于如下代码:
#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;
}
那么按照 CPU切片交换运行两个线程来算,应该是每个线程在切片时间内输出几行,如此交替循环,如下:
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