临界区与信号量区别(数量上的区别)
临界区(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);
}