windows多线程系列005 利用信号量实现线程同步

在这一节,我们将讲解关于windows信号量的知识, 信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作,首先先介绍和windows信号量有关的两个API:创建信号量、释放信号量
HANDLE WINAPI CreateSemaphore(            
_In_opt_  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes
_In_      LONG lInitialCount,
_In_      LONG lMaximumCount,
_In_opt_  LPCTSTR lpName
);
第一个参数:安全属性,如果为NULL则是默认安全属性
第二个参数:信号量的初始值,要>=0且<=第三个参数
第三个参数:信号量的最大值
第四个参数:信号量的名称
返回值:指向信号量的句柄,如果创建的信号量和已有的信号量重名,那么返回已经存在的信号量句柄
BOOL WINAPI ReleaseSemaphore(           
_In_       HANDLE hSemaphore,
_In_       LONG lReleaseCount,
_Out_opt_  LPLONG lpPreviousCount
);
第一个参数:信号量句柄
第二个参数:释放后,信号量增加的数目
第三个参数:信号量增加前的值存放的地址,如果不需要则为NULL
返回值:释放是否成功
以上两个函数头文件:windows.h (另外还有个函数OpenSemaphore()可以打开其它进程创建的信号量)                                   
下面通过一个例子来说明信号量如何使用,这是一道IT公司笔试题:编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。

分析:这里我们要让三个线程按顺序依次打印ABC,即当一个线程在打印A时,另外两个线程不能够打印,而且打印完A以后,接下来必须打印B。我们使用三个信号量分别控制A B C的打印,打印完A就释放B的信号量,打印完B就释放C的信号量,打印完C就释放A的信号量。具体见下面代码:

#include<string>
#include<iostream>
#include<process.h>
#include<windows.h>
using namespace std;
HANDLE hsem1, hsem2, hsem3;

//线程绑定的函数返回值和参数是确定的,而且一定要__stdcall
unsigned __stdcall threadFunA(void *)
{
	for (int i = 0; i < 10; i++){
		WaitForSingleObject(hsem1, INFINITE);//等待信号量
		cout << "A";
		ReleaseSemaphore(hsem2, 1, NULL);//释放信号量
	}
	return 1;
}
unsigned __stdcall threadFunB(void *)
{
	for (int i = 0; i < 10; i++){
		WaitForSingleObject(hsem2, INFINITE);//等待信号量
		cout << "B";
		ReleaseSemaphore(hsem3, 1, NULL);//释放信号量
	}
	return 2;
}
unsigned __stdcall threadFunC(void *)
{
	for (int i = 0; i < 10; i++){
		WaitForSingleObject(hsem3, INFINITE);//等待信号量
		cout << "C";
		ReleaseSemaphore(hsem1, 1, NULL);//释放信号量
	}
	return 3;
}


int maintest003()
{
	//创建信号量
	hsem1 = CreateSemaphore(NULL, 1, 1, NULL);
	hsem2 = CreateSemaphore(NULL, 0, 1, NULL);
	hsem3 = CreateSemaphore(NULL, 0, 1, NULL);

	HANDLE hth1, hth2, hth3;

	//创建线程
	hth1 = (HANDLE)_beginthreadex(NULL, 0, threadFunA, NULL, 0, NULL);
	hth2 = (HANDLE)_beginthreadex(NULL, 0, threadFunB, NULL, 0, NULL);
	hth3 = (HANDLE)_beginthreadex(NULL, 0, threadFunC, NULL, 0, NULL);

	//等待子线程结束
	WaitForSingleObject(hth1, INFINITE);
	WaitForSingleObject(hth2, INFINITE);
	WaitForSingleObject(hth3, INFINITE);

	//一定要记得关闭线程句柄
	CloseHandle(hth1);
	CloseHandle(hth2);
	CloseHandle(hth3);
	CloseHandle(hsem1);
	CloseHandle(hsem2);
	CloseHandle(hsem3);
	system("pause");
	return 1;
}
参考:http://www.cnblogs.com/TenosDoIt/p/3601252.html




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

余莫星辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值