贵州做网站公司
贵州做网站公司~专业!靠谱!
10年网站模板开发经验,熟悉国内外开源网站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等网站程序,可为您提供网站建设,网站克隆,仿站,网页设计,网站制作,网站推广优化等服务。我们专注高端营销型网站,企业官网,集团官网,自适应网站,手机网站,网络营销,网站优化,网站服务器环境搭建以及托管运维等。为客户提供一站式网站解决方案!!!

【并发编程六】c++进程通信——信号量(semaphore)

来源:网络转载 时间:2023-09-04 20:45:30

【并发编程六】c++进程通信——信号量(semaphore)

  • 一、概述
  • 二、信号量
  • 三、原理
  • 四、过程
    • 1、进程A过程
    • 2、进程B过程
  • 五、demo
    • 1、进程A
    • 2、进程B
  • 六、输出
  • 七、windows api介绍
    • 1. 创建信号量 CreateSemaphore()
    • 2. 打开信号量 OpenSemaphore()
    • 3. 等待 WaitForSingleObject()
    • 4. 递增信号量的当前资源计数ReleaseSemaphore()
    • 5. 关闭句柄 CloseHandle()
  • 八、信号量使用场景

为了防⽌多进程竞争共享资源,⽽造成的数据错乱,所以需要保护机制,使得共享的资源,在任意时刻只能被⼀个进程访问(或者有限个进程访问)。正好,信号量就实现了这⼀保护机制。

一、概述

信号量的概念是由荷兰计算机科学家艾兹赫尔·戴克斯特拉(Edsger W. Dijkstra)发明的,广泛的应用于不同的操作系统中。在系统中,给予每一个进程一个信号量,代表每个进程目前的状态,未得到控制权的进程会在特定地方被强迫停下来,等待可以继续进行的信号到来。如果信号量是一个任意的整数,通常被称为计数信号量(Counting semaphore),或一般信号量(general semaphore);如果信号量只有二进制的0或1,称为二进制信号量(binary semaphore)

  • 信号量是操作系统提供的一种协调共享资源访问的方法。信号量则由操作系统进行管理,地位高于进程,操作系统保证信号量的原子性。

二、信号量

信号量(英语:semaphore)又称为信号标或者信号灯,是一个同步对象,用于保持在0至指定最大值之间的一个计数值。当线程完成一次对该semaphore对象的等待(wait)时,该计数值减一;当线程完成一次对semaphore对象的释放(release)时,计数值加一。当计数值为0,则线程等待该semaphore对象不再能成功直至该semaphore对象变成signaled状态。semaphore对象的计数值大于0,为signaled状态;计数值等于0,为nonsignaled状态。

三、原理

一个信号量 S 是个整型变量,它除了初始化外只能通过两个标准原子操作:wait () 和 signal() 来访问:

  • 操作 wait() 最初称为 P(荷兰语proberen,测试);成功则,S–;
  • 操作 signal() 最初称为 V(荷兰语verhogen,增加);成功则,S++;

四、过程

我们以windows api的接口为例,讲解下信号量是如何在进程A和进程B间做到进程间同步的。

1、进程A过程

  • 1.1、CreateSemaphore():创建一个名字为Semaphore的信号量,该信号量初始可使用的资源数为0。即S=0.
  • 1.2、WaitForSingleObject():等待信号量>0,就是等待信号量的资源数大于0时。成功后就是S–。(启动进程A后,此处会一直等待,因为创建的信号量初始的值=0,直到进程B打开进程A的信号量,并且释放一个可以使用的资源时,S变成1,才可以继续,进行后面的程序)
  • 1.3、在屏幕打印文字。
  • 1.4、ReleaseSemaphore():释放上面wait成功时占用的1个资源数。执行成功后就是S++。
  • 1.5、等待5s。

2、进程B过程

  • 2.1、OpenSemaphore():打开进程A创建的信号量,名字为Semaphore
  • 2.2、ReleaseSemaphore():递增信号量的当前资源计数,就是S++。S=1
  • 2.3、WaitForSingleObject():等待信号量>0,就是等待信号量的资源数大于0时。成功后就是S–。
  • 2.4、在屏幕打印文字。
  • 2.5、ReleaseSemaphore():释放上面wait成功时占用的1个资源数。成功后就是S++。
  • 2.6、等待5s。

五、demo

1、进程A

  • main.cpp
#include <windows.h> #include <iostream> using namespace std;#define BUF_SIZE 4096int main(int argc, TCHAR* argv[]) {cout << "processA:" << endl << endl;// 创建信号量HANDLE handle = CreateSemaphore(NULL,0,10,"Semaphore");cout << "创建信号量成功,并等待进程B释放一个可以使用的资源数......." << endl<<endl;for (int i = 0; i < 5; i++){cout << "进入新号量等待区" << endl;DWORD ret = WaitForSingleObject(handle,100000);if (0 == ret){cout << "processA:" << i << ".....s--" << endl;}ReleaseSemaphore(handle , 1,NULL);cout << "释放1个信号并等待5秒中....." << "s++" << endl << endl;Sleep(5000);} system("pause"); //等待其他进程读取数据// 关闭句柄CloseHandle(handle);return 0; }
  • CmakeList.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0) PROJECT(process) ADD_EXECUTABLE(processA main.cpp) ADD_SUBDIRECTORY(processB) SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")

2、进程B

  • main.cpp
#include <iostream> #include <windows.h> using namespace std;#define BUF_SIZE 4096int main() {cout << "processB:" << endl << endl;// 打开共享的文件对象HANDLE handle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, // 访问标志TRUE, // 继承标志"Semaphore"); // 信号量名if (nullptr != handle){cout << "打开信号量:成功" << endl;}else{cout << "打开信号量:失败" << endl;}cout << "释放1个可以使用的资源数:s++" << endl<<endl;ReleaseSemaphore(handle, 1, NULL);for (int i = 0; i < 5; i++){cout << "进入新号量等待区" << endl;DWORD ret = WaitForSingleObject(handle,100000);if (0 == ret){cout << "processB:" << i <<".....s--"<< endl;}ReleaseSemaphore(handle, 1, NULL);cout << "释放1个信号并等待5秒中....." << "s++" << endl << endl;Sleep(5000);}system("pause");return 0; }
  • CmakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)SET(TARGET "childprocess")ADD_EXECUTABLE(processB main.cpp)SET(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib") SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")

六、输出

构建、编译、先启动进程A,输出如下。(备:因为创建信号量时,初始化资源数为0,即S=0,如果你不启动进程B释放可用的资源数,进程A在此处会等待直到超时)

再启动进程B输出如下。

七、windows api介绍

本文我们以windows的api接口为例,其实Linux下接口原理是一样的,用法也类似,我们不再过多介绍。

1. 创建信号量 CreateSemaphore()

函数说明:

第一个参数表示安全控制,一般直接传入NULL。
第二个参数表示初始资源数量。
第三个参数表示最大并发数量。
第四个参数表示信号量的名称,传入NULL表示匿名信号量。

HANDLE WINAPI CreateSemaphore( _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性,通常为NULL_In_ LONG lInitialCount, // 可用资源数目,就是信号量S的初始值_In_ LONG lMaximumCount, // 信号量对象可处理的最大资源数,就是S的最大值_In_opt_ LPCTSTR lpName // 信号量的名称,进程之间可共享 );

2. 打开信号量 OpenSemaphore()

函数说明:

第一个参数表示访问权限,对一般传入SEMAPHORE_ALL_ACCESS。详细解释可以查看MSDN文档。
第二个参数表示信号量句柄继承性,一般传入TRUE即可。
第三个参数表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个信号量。

HANDLE WINAPI OpenSemaphore( _In_ DWORD dwDesiredAccess, // 访问的权限_In_ BOOL bInheritHandle, // 子进程继承信号量对象与否_In_ LPCTSTR lpName // 信号量对象名称 );

3. 等待 WaitForSingleObject()

等待指定对象处于信号状态或超时间隔已过。
本文中,就是等待信号量S>0时,进入。如果信号量S<=0,那就是等待,直到设置的超时时间。

DWORD WINAPI WaitForSingleObject( _In_ HANDLE hHandle, // 内核对象句柄_In_ DWORD dwMilliseconds // 单位,毫秒。对象被触发前的等待时间,INFINITE表示无限时间阻塞等待,简单来说就是死等 );

4. 递增信号量的当前资源计数ReleaseSemaphore()

函数说明:

第一个参数是信号量的句柄。
第二个参数表示增加个数,必须大于0且不超过最大资源数量。
第三个参数可以用来传出先前的资源计数,设为NULL表示不需要传出。

BOOL WINAPI ReleaseSemaphore( _In_ HANDLE hSemaphore, // 信号量对象句柄_In_ LONG lReleaseCount, // 释放使用的资源树_Out_opt_ LPLONG lpPreviousCount // 一般设为null );

当一个线程使用完信号量对象控制的有限资源后,应该调用ReleaseSemaphore,释放使用的资源,使信号量对象的当前资源计数得到恢复

5. 关闭句柄 CloseHandle()

BOOL WINAPI CloseHandle( _In_ HANDLE hObject // 句柄 );

八、信号量使用场景

  • 多进程访问统一资源。
  • 资源限流。
    比如:数据库连接池,同时进行连接的线程有数量限制,连接不能超过一定的数量,当连接达到了限制数量后,后面的线程只能排队等前面的线程释放了数据库连接才能获得数据库连接。

关于资源限流,我们举例说下。
1、一个厕所有3个坑,进厕所需要拿1个号牌(5毛钱一个号牌)。
2、肯定要设置为信号量的初始值为S=3,就是厕所的号牌数量为3。
3、进去一个人,号牌减1,S–。
4、当进入3个人时,没有号牌了,S=0,第四个人就要等待了,
5、等待厕所中的其中一个人上完大号出来,把号牌交出去,S++,其他人才可以拿着号牌进去。
(其实,你想想网站服务器控制并发访问和限流,不也是这个原理吗?)

  • 参考
    1、多线程面试题系列(8):经典线程同步 信号量Semaphore
    2、 信号量与管程
    3、 信号量及其使用和实现(超详细)
    4、 维基百科-信号量
    4、 信号量限流,高并发场景不得不说的秘密
标签:sem-

ps怎么让皮肤变白?使用软件版本:PS CS6版本使用Photoshop对人物皮肤进行如下美白:1.打开PS软件,放入要蒙皮的人的图像,Ctrl J复制一层;2.执行 amp的设置参数过滤gt杂散gt减少杂散gt先进gt每个频道在菜单栏中如下:红色强度10-保留细节100%绿色强度10-保留细节6%蓝色强度10-保留细节6%。3.执行命令 "滤镜gt锐化gtUSM锐化 "在菜单栏中。设置参数个数:...

怎样用1元钱叠戒指?材料:一元(此处用100元,方法相同)。具体步骤:1。向下折一条边约0.5~1CM。这一边的大小决定了心脏的大小。2.把纸币对折。3.向中心线对折两边。4.折好后,转身在顶部折一个角。(折叠后的长度是心脏的长度)5。反过来~从下往上分别折叠左右两边。6.然后把刚折好的部分从上往下折。7.完成以上步骤后,拿起整张钞票。从后向前折叠波纹。(这个波纹的厚度就是戒指的厚度。) 8.最后...

打印的Word文档出现第{PAGE*MERGEFORMAT}页怎么办?解决方法如下:1。单击“在word中插入页码”并按ALT F9在显示函数变量代码和函数变量结果之间切换,以更改“页码”。合并格式“到正常页码。2、 使用word选项设置更改页码显示模式。以WORD2010为例:1。单击“文件”菜单栏下的“选项”;2。切换到高级页。在“显示单据内容”中,取消“显示字段编码不显示值字段”前的勾选,单...

现在建设网站是网络发展过程中比较重要的一种营销方式,许多的企业在营销推广过程中都会选择建设网站,并且不断的进行优化,那么专业网站优化应该怎样做?下面由贵州做网站公司说一下。  什么样的优化才是专业网站优化  网站优化指在了解搜索引擎自然排名机制的基础之上,对网站进行部及外部的调整优化,改进网站在搜容索引擎中关键词的自然排名,获得更多的展现量,吸引更多目标客户...

随着互联网网络普及和社会经济格调的不断上升,网站营销已经成了现在所有企业的公司商家在营销推广上的首现模式。由于在互联网平上的全网营销推广方式的特殊性,它的传播受众...

网站中的横幅广告跟实体宣传中的广告牌性质是一样的,只是说一个在现实中标示出来,一个是在互联网中标示出来,实体的大家都很清楚能看到,因为在大街大巷中都能随处看到广告牌,那么今天我们说介绍一下网页中的广告条性质和分布:网页中的广告条就是指网幅广告、旗帜广告、横幅广告(网络广告的主要形式一般使用JPG、PNG和GIF格式的图像文件,JPG和PNG格式的图像是静态图形,GIF格式的图像为小动画)。PC端网...

TOP