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

  1. 关键段 CriticalSection
  2. 互斥量Mutex
  3. 事件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<iostream>
#include <windows.h> using namespace std; const int THREAD_NUM = 10;
int g_Num = 0;
CRITICAL_SECTION g_csVar; //创建关键段cs
HANDLE 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;
}

运行结果如下所示:

windows多线程(八) 信号量Semaphore的更多相关文章

  1. windows多线程同步--信号量

    推荐参考博客:秒杀多线程第八篇 经典线程同步 信号量Semaphore   首先先介绍和windows信号量有关的两个API:创建信号量.释放信号量   HANDLE WINAPI CreateSem ...

  2. windows核心编程-信号量(semaphore)

    线程同步的方式主要有:临界区.互斥区.事件.信号量四种方式. 前边讲过了互斥器线程同步-----windows核心编程-互斥器(Mutexes),这章我来介绍一下信号量(semaphore)线程同步. ...

  3. 多线程相关------信号量Semaphore

    Semaphore用于对资源进行计数.允许一定数量的线程同时访问该资源.可以用于进程间同步 相关函数 CreateSemaphore 创建或打开一个信号量对象 HANDLE WINAPI Create ...

  4. 总结windows多线程同步互斥

    windows多线程同步互斥--总结 我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同 ...

  5. windows多线程同步互斥--总结

    我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同步--临界区 windows多线程同步 ...

  6. windows多线程同步--临界区

    推荐参考博客:秒杀多线程第五篇 经典线程同步 关键段CS   关于临界区的观念,一般操作系统书上面都有. 适用范围:它只能同步一个进程中的线程,不能跨进程同步.一般用它来做单个进程内的代码快同步,效率 ...

  7. 秒杀多线程第八篇 经典线程同步 信号量Semaphore

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <且不超过最大资源数量. 第三个參数能够用来传出先前的资源计数,设为NULL表示不须要传出. 注意:当 ...

  8. 转---秒杀多线程第八篇 经典线程同步 信号量Semaphore

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  9. 多线程面试题系列(8):经典线程同步 信号量Semaphore

    前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数 ...

  10. C++多线程同步之Semaphore(信号量)

    一.线程间同步的几种方式 从上篇博文中可以发现,当多个线程对同一资源进行使用时,会产生“争夺”的情况,为了避免这种情况的产生,也就出现了线程间的同步这个技术.线程间的同步有多种方式,在接下来的博文中我 ...

随机推荐

  1. 2_C语言中的数据类型 (二)进制

    1.1       二进制数.位.字节与字 我们习惯于十进制的数:10,12等 一个位只能表示0,或者1两种状态,简称bit,一个位是一个bit 一个字节为8个二进制,称为8位,简称BYTE,8个比特 ...

  2. 洛谷 P4593 [TJOI2018]教科书般的亵渎

    洛谷 P4593 [TJOI2018]教科书般的亵渎 神仙伯努利数...网上一堆关于伯努利数的东西但是没有证明,所以只好记结论了? 题目本质要求\(\sum_{i=1}^{n}i^k\) 伯努利数,\ ...

  3. css绘制常见的几何图形

    前言:终于我的大一生活结束了,迎来了愉快的暑假,大家都开始了各自的忙碌.一直忙着一些项目的事情,终于决定今天要更新一篇博客了,对上一阶段的学习做简单的总结. 这次我主要总结一下用Css绘制各种形状的技 ...

  4. 简单可行的code review规则

    前言 曾经有一段垃圾代码放在我的面前,我没有拒绝,等我真正开始接手的时候我才后悔莫及,程序员最痛苦的事莫过于此! 每当接手别人的代码,都有一种想重新写一遍的感觉,等到别人再来接手你的代码时,同样的感觉 ...

  5. 火狐浏览器油猴子GreaseMonkey使用教程

    火狐浏览器油猴子GreaseMonkey使用教程 首先下载火狐浏览器 安装成功后用火狐浏览器打开链接,界面如下 然后搜索GreaseMonkey. 搜索结果,图标是个小猴子,然后添加到火狐浏览器,成功 ...

  6. [Unity Shader] 切线空间的法线贴图

    切线空间的法线贴图,可以这样理解: #纹理坐标是从0到1,它的坐标是x向右,y向下 #顶点坐标是从-1到-1,坐标是x向右,y向上 1 由表面上某点的切线Tangent.副切线Bitangent.法线 ...

  7. oracle存储过程 关于update的动态SQL-工作心得

    本随笔文章,由个人博客(鸟不拉屎)转移至博客园 发布时间: 2018 年 12 月 20 日 原地址:https://niaobulashi.com/archives/oracle-procedure ...

  8. 如何掌握 Kubernetes ?系统学习 k8s 的大纲一份

    深度剖析 Kubernetes 深度剖析 k8s 如何学习 Kubernetes ?如何入门 Kubernetes? 为了帮帮初学者,2018 年 InfoQ 旗下(就是你知道的那个 InfoQ 哇) ...

  9. slotting filter笔记

    1.slot filling是为了让用户的意图转化为明确的指令而补全信息的过程. 2.准入条件 从一个开放域转入到封闭域,或者从一个封闭域转入到另一个封闭域,中间的跳转是需要逻辑判断的,而这个逻辑判断 ...

  10. Ipython使用

    目录 Ipython说明 Ipython使用 安装使用 TAB键自动补全 内省(?命令) 执行系统命令(!) 与操作系统交互 %run命令执行文件代码 %paste %cpaste命令执行剪贴板代码 ...