一个有趣的多线程问题

师弟问了个非常有趣的多线程问题,之前没有关注,这里写下自己的心得。

对于如下代码:

#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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值