博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
windows多线程(八) 信号量Semaphore
阅读量:5324 次
发布时间:2019-06-14

本文共 2588 字,大约阅读时间需要 8 分钟。

如果你看到了这里,我就认为你已经对掌握了有关关键段 CriticalSection、互斥量Mutex和事件Event有关的内容,所以最基本的东西就不再介绍了。如果没有掌握上面说的内容,可以看这里:

一、信号量相关函数说明

(一) 创建信号量CreateSemaphore
1.函数原型
HANDLE WINAPI CreateSemaphore(        _In_opt_ LPSECURITY_ATTRIBUTES  lpSemaphoreAttributes,        _In_     LONG lInitialCount,        _In_     LONG lMaximumCount,        _In_opt_ LPCWSTR lpName        );
2.参数说明
  • 第一个参数lpSemaphoreAttributes,表示安全属性。如果是NULL,就表示使用默认属性。
  • 第二个参数lInitialCount,信号量的初始数值,必须大于或等于0,并且小于或等于lMaximumCount
  • 第三个参数lMaximumCount,信号量的最大值,即最大并发数。
  • 第四个参数lpName,信号量的名字,是一个字符串,任何线程(或进程)都可以根据这一名称引用到这个信号量,这个值可以是NULL,表示产生一个匿名信号量。

  • 返回值: 如果成功就返回一个handle,否则传回NULL。

(二) 打开信号量OpenSemaphore
1.函数原型
HANDLE WINAPI OpenSemaphore(        _In_ DWORD dwDesiredAccess,        _In_ BOOL bInheritHandle,        _In_ LPCSTR lpName        );
2.参数说明
  • 第一个参数dwDesiredAccess,表示访问权限,一般传入SEMAPHORE_ALL_ACCESS。
  • 第二个参数bInheritHandle,表示信号量句柄继承性,一般传入True。
  • 第三个参数lpName,需要打开的信号量的名称。

  • 返回值: 如果成功就返回信号量handle,否则传回NULL。

(三) 信号量解除锁定ReleaseSemaphore

这个函数功能是实现信号量计数器增加一个值,该值通常是1,但不会超过创建信号量时指定的lMaximumCount

1.函数原型
BOOL WINAPI ReleaseSemaphore(        _In_ HANDLE hSemaphore,        _In_ LONG lReleaseCount,        _Out_opt_ LPLONG lpPreviousCount        );
2.参数说明
  • 第一个参数hSemaphore,信号量的句柄。
  • 第二个参数lReleaseCount,表示信号量值增加的个数,必须大于0且不超过最大资源数,一般为1。
  • 第三个参数lpPreviousCount,传出先前信号量的计数值,设置为NULL表示不需要传出。

  • 返回值: 如果成功就返回True,否则传回False。

(四) 关闭信号量

由于信号量是一个内核对象,关闭时直接调用CloseHandle()就可以了。

二、实例

使用信号量同样可以实现线程的同步,实现每个线程按顺序依次给全局资源加一,代码如下:

//  信号量演示#include
#include
using namespace std;const int THREAD_NUM = 10;int g_Num = 0;CRITICAL_SECTION g_csVar; //创建关键段csHANDLE g_ThreadSema; //创建内核对象,用来初始化信号量DWORD WINAPI Func(LPVOID);int main(){ InitializeCriticalSection(&g_csVar); g_ThreadSema = CreateSemaphore(NULL, 0, 1, NULL); //创建匿名信号量,初始资源为零,最大并发数为1, HANDLE handle[THREAD_NUM]; DWORD ThreadId[THREAD_NUM]; int i = 0; while (i < THREAD_NUM) { handle[i] = CreateThread(NULL, 0, Func, &i, 0, &ThreadId[i]); WaitForSingleObject(g_ThreadSema, INFINITE); //等待信号量资源数>0 i++; } WaitForMultipleObjects(THREAD_NUM, handle, true, INFINITE); CloseHandle(g_ThreadSema); //销毁信号量 DeleteCriticalSection(&g_csVar);//销毁关键段cs for (i = 0; i < THREAD_NUM; i++) { CloseHandle(handle[i]); } return 0;}DWORD WINAPI Func(LPVOID p){ int nThreadNum = *(int*)p; EnterCriticalSection(&g_csVar); cout << "线程编号为: " << nThreadNum << " 全局资源值为:" << ++g_Num << endl; LeaveCriticalSection(&g_csVar); ReleaseSemaphore(g_ThreadSema, 1, NULL); //信号量资源数加一 return 0;}

运行结果如下所示:

825979-20180603204250890-1926628340.png

转载于:https://www.cnblogs.com/ay-a/p/9130418.html

你可能感兴趣的文章
App Store最新审核指南(2015年3月更新版)
查看>>
织梦MIP文章内容页图片适配百度MIP规范
查看>>
点击复制插件clipboard.js
查看>>
[Kali_BT]通过低版本SerialPort蓝牙渗透功能手机
查看>>
C语言学习总结(三) 复杂类型
查看>>
HNOI2018
查看>>
【理财】关于理财的网站
查看>>
Ubunt中文乱码
查看>>
《当幸福来敲门》读后
查看>>
【转】系统无法进入睡眠模式解决办法
查看>>
省市县,循环组装,整合大数组
查看>>
stm32中字节对齐问题(__align(n),__packed用法)
查看>>
like tp
查看>>
posix多线程有感--线程高级编程(线程属性函数总结)(代码)
查看>>
spring-使用MyEcilpse创建demo
查看>>
DCDC(4.5V to 23V -3.3V)
查看>>
kettle导数到user_用于left join_20160928
查看>>
activity 保存数据
查看>>
typescript深copy和浅copy
查看>>
linux下的静态库与动态库详解
查看>>