多线程同步信号量

临界区与信号量区别(数量上的区别)

临界区(CriticalSection): 一次只允许一个线程访问资源。

信号量(Semaphore):  允许N个线程再同一时刻访问同一资源。

 

信号量备注:

(1)使用CreateSemaphore()创建信号量时要指出允许的最大资源计数喝当前可用资源计数。(最大资源计数为1时 则与临界区一样)

(2)一般将当前可用资源计数设置为最大值,每增加一个线程对资源的访问,可用资源计数-1,只要当前可用资源计数是>0,就可发出信号。当可用计数减小到0,则说明当前占用资源线程数已达所允许的最大值,不允许其他线程的进入,此时无法发出信号。

(3)线程再处理完共享资源后,通过ReleaseSemaphore()函数将当前可用资源计数+1。

 

 

创建信号量

HANDLE WINAPI CreateSemaphore(

                                                            LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,

                                                            LONG lInitialCount,

                                                            LONG lMaximumCount,

                                                            LPCTSTR lpName  );

 

参数:

lpSemaphoreAttributes: 安全属性,如果为NULL则默认。

lInitialCount:                信号量的初始值,要>=0且<=第三个参数。

lMaximumCount:         信号量的最大值。

lpName :                      表示信号量的名称,传入NULL表示匿名信号量。

 

返回值:

成功:(1)返回句柄。

          (2)如果创建的信号量和已有的信号量重名,那么返回已经存在的信号量句柄。

失败: 返回NULL。

 

 

 

对指定的信号量增加指定值

BOOL ReleaseSemaphore(

                                            HANDLE hSemaphore,

                                            LONG lRelesesCount,

                                            LPLONG lpPreviousCount);

 

参数:

hSemaphore:     信号量句柄。

lRelesesCount:   信号量对象再当前基础上索要增加的值

lpPreviousCount:向返回信号量上次值的变量的指针

 

返回值:

成功:TRUE;

失败:FALSE;

 

 

注:内核对象:文件、文件映射、进程、线程、安全和同步对象等

 

等待一个内核对象变为已通知状态(这里可用来对信号量使用)

DWORD  WaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds);

 

关闭一个内核对象(这里可用来对信号量使用)(没有释放对象,引用计数-1)

BOOL CloseHandle(HANDLE hPbject);

 

利用Semaphore实现进程只有一个实例!

(1)有些程序不允许运行同一个程序的多个实例运行(例如以独占方式使用串行口,端口等)。

(2)由此引出进程互斥的问题,Semaphore实现进程互斥的方法:

        进程再第一次启动时成功创建命名Semaphpre实例成功,此后进程实例第二次创建GetLastError会返回ERROR_ALREADY_EXISTS,从而保证进程再系统中只能存在一个实例。

 

 

#include<windows.h>
#include<process.h>
#include<stdio.h>

HANDLE hSemaphore;
//定义汽车结构体
struct CAR
{
	char name[20];
	int  time;
};

//线程
void ThreadFun(void* paramer);

int main()
{
	//L是表示为unicode编码
	//设置信号量,最多可同时3个
	hSemaphore = CreateSemaphore(NULL, 3, 3, L"停车场");
	if (GetLastError() == ERROR_ALREADY_EXISTS)
	{
		printf("已有进程打开,不允许两个进程同时打开!\n");
		printf("任意键退出!\n");
		getchar();
		return -1;
	}
	HANDLE hArry[5] = {};
	for (int i = 0; i < 5; i++)
	{
		CAR * pcar = new CAR;
		sprintf_s(pcar->name, "车辆%c", 'A' + i);
		pcar->time = 3 + i * 2;
		hArry[i] = (HANDLE)_beginthread(ThreadFun, 0, pcar);
	}
	//等待所有退出
	WaitForMultipleObjects(5, hArry, true, INFINITE);
	return 0;
}

void ThreadFun(void * paramer)
{
	//等待信号量为空时
	WaitForSingleObject(hSemaphore,INFINITE);
	CAR * pcar = (CAR*)paramer;
	printf("%s进入停车场,停车%d秒!\n", pcar->name, pcar->time);
	Sleep(pcar->time * 1000);
	printf("%s驶出停车场!\n", pcar->name);
	delete pcar;
	//当前可用资源计数+1
	ReleaseSemaphore(hSemaphore, 1, NULL);
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值