信号量
- 互斥量:某段时间只能让一个线程运行,其他休眠。
- 信号量:多个线程运行,其他线程休眠
- 临界区:只能让一个线程运行,其他休眠。
- 原子操作:操作速度最快,因为他不需要等待和切换线程。
- 事件也可以实现线程互斥。
1.信号量
主要解决线程通信,实现同一时刻多个线程同时访问一个资源,当同一时刻只有一个线程在访问时它就和互斥量是一样的,所以有时说信号量是Mutex的退化版。它也是系统内核对象. 系统提供相关的API有:
CreateSemaphore
OpenSemaphore
ReleaseSemaphore
WaitForSingleObject/WaitForMultipleObjects
CloseHandle
2.理解
-
Semaphore分为单值和多值两种,前者只能被一个线程获得,后者可以被若干个线程获得。以 一个停车场是运作为例。为了简单起见,假设停车场只有三个车位,一开始 三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处 等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。
- Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。一般的用法是用于串行化对critical section代码的访问,保证这段代码不会被并行的运行。
Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。一般的用法是,用于限制对于某一资源的同时访问。
3.函数的参数
CloaseHandle(thread);thread线程执行完毕,然后退出。
当信号量设置是1,也可以实现互斥。
信号量遇到0就死等,遇到其他数,减1.
2.例子
例一:
//关卡的作用 #include <stdio.h> #include <stdlib.h> #include <Windows.h> #define id "haihua" #define MAX 5 //0无限等待 DWORD WINAPI myworker(void *p) { int *pint = p; printf("\nmyworker%d is running", *pint); HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, id);//打开一个信号 if (myhsem) //myheasm!=null { printf("\nmyworker%d is waitting", *pint); //初始化信号为0,为0就会死锁,0,信号量不减去 //WaitForSingleObject不为 0的情况下,信号量-1 if (WaitForSingleObject(myhsem,INFINITE)==WAIT_OBJECT_0)//等到了信号 { printf("\nmyworker%d is gettting", *pint); Sleep(3000); printf("\nmyworker%d is leaving,", *pint); ///ReleaseSemaphore(myhsem, 1, NULL);//释放资源 ,+1 CloseHandle(myhsem);//执行完成退出 } } return 1; } int main() { //创建信号对象, HANDLE hSEM = CreateSemaphore(NULL, 0, MAX, id);//开辟一个信号,最大计数是5.0 int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; HANDLE hd[10] = { 0 }; for (int i = 0; i < 10;i++) { hd[i] = CreateThread(NULL, 0, myworker, a + i, 0, NULL);//创建是个线程 } Sleep(5000); printf("激活线程"); ReleaseSemaphore(hSEM, MAX, NULL); //最多一次放过5 WaitForMultipleObjects(10, hd, TRUE, INFINITE); CloseHandle(hSEM); system("pause"); }
例二:
#include <stdio.h> #include <stdlib.h> #include <Windows.h> int num = 0; DWORD WINAPI add(void*p) { HANDLE myhsem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, "xiaobin");//打开一个信号 if (myhsem) //myheasm!=null { if (WaitForSingleObject(myhsem, INFINITE) == WAIT_OBJECT_0)//等到了信号 { for (int i = 0; i < 100000; i++) { num++; } ReleaseSemaphore(myhsem, 1, NULL); CloseHandle(myhsem);//执行完成退出 } } else { printf("信号量获取失败\n"); } } int main() { //创建信号对象, HANDLE hSEM = CreateSemaphore(NULL, 0, 1, "xiaobin");//开辟一个信号,最大计数是5.0 HANDLE hd[64] = { 0 }; for (int i = 0; i < 64; i++) { hd[i] = CreateThread(NULL, 0, add,NULL, 0, NULL);//创建是个线程 } Sleep(2000); printf("激活线程"); ReleaseSemaphore(hSEM, 1, NULL); WaitForMultipleObjects(64, hd, TRUE, INFINITE); printf("%d", num); CloseHandle(hSEM); system("pause"); }
人怂胆子小,手拿大刀跑。