windows环境利用semophore机制进行线程同步
semophore是信号量的意思,常用于PV操作,所谓PV操作就是pend(等待,直到有资源可用,并且消耗资源)
V就是释放资源。
semophore和mutex区别,mutex本意为互斥,用于线程独占资源,常用于临界区访问锁住mutex,
当线程A对mutex加锁后,其他线程不能反问临界资源,也不能加锁,直到线程A解锁,其他线程才能访问。
而semophore则可以在不同的线程之间进行pv操作,semophore可以设置最多有多少个信号量,以及初始
的信号量,当调用V操作的时候信号量数量增加一个,调用P操作时候信号量数量减少一个,但是不能超过最多
的信号量。信号量是一个非负数。
打个比方,一辆车只有一把钥匙,mutex就是这把钥匙,谁有这把钥匙才能开车,开完车把钥匙归还或者给
下一个等待的人。现在有一辆公交车,最多容纳二十个人,二十就是信号量的最大值,每个人就是一个信号量,
当人满的时候其他的人就不能上车,直到有人下车,其他人才能上车。
semophore主要适用于windows环境下的同步
下面介绍下semophore
1 创建信号量
HANDLE WINAPI CreateSemaphore(
_In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes
_In_ LONG lInitialCount,
_In_ LONG lMaximumCount,
_In_opt_ LPCTSTR lpName
);
第一个参数:安全属性,如果为NULL则是默认安全属性
第二个参数:信号量的初始值,要>=0且<=第三个参数
第三个参数:信号量的最大值
第四个参数:信号量的名称
返回值:指向信号量的句柄,如果创建的信号量和已有的信号量重名,那么返回已经存在的信号量句柄
2打开其他进程中的信号量
HANDLE WINAPI OpenSemaphore(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ LPCTSTR lpName
);
dwDesiredAccess:指定想要的访问权限,SEMAPHORE_ALL_ACCESS 请求对事件对象的完全访问,SEMAPHORE_MODIFY_STATE 修改状态权限,使用 ReleaseSemaphore函数需要该权限;
bInheritHandle:是否希望子进程继承信号量对象的句柄,一般设置为false;
lpName:要打开的信号量对象的名称;
3等待信号量
DWORD WINAPI WaitForSingleObject(
_In_ HANDLE hHandle,
_In_ DWORD dwMilliseconds
);
hHandle:指向内核对象的句柄;
dwMilliseconds:线程最大等待多长时间,直到该对象被触发。经常使用INFINITE,表示阻塞等待。
WaitForSingleObject为等待资源的函数,等待内核对象被触发的通用函数,在这里用于等待信号量,我们之前说过信号量的资源数是非负整数,当信号量数量
大于0,那么该函数会将信号量-1,并且返回,线程继续执行后续操作。如果信号量资源数为0,那么该线程处于等待状态,阻塞等待信号量被激活。
4 释放信号量
BOOL WINAPI ReleaseSemaphore(
_In_ HANDLE hSemaphore,
_In_ LONG lReleaseCount,
_Out_opt_ LPLONG lpPreviousCount
);
hSemaphore:信号量内核对象的句柄;
lReleaseCount:释放自己使用的资源数目,加到信号量的当前资源计数上,通常会传1,当然是根据线程使用的资源数目而定。
lpPreviousCount:返回当前资源计数的原始值,应用程序很少会用到这个值,所以一般置为NULL;
当一个线程使用完信号量对象控制的有限资源后,应该调用ReleaseSemaphore,释放使用的资源,使信号量对象的当前资源计数得到恢复。
5关闭内核对象的句柄
BOOL WINAPI CloseHandle(
_In_ HANDLE hObject
);
hObject:指向内核对象的句柄
和其他内核对象一样,无论以什么方式创建内核对象,我们都必须通过调用CloseHandle向系统表明结束使用内核对象。如果传入的句柄有效,系统将获得内核对象数据结构的地址,并将结构中的使用计数减1,
如果使用计数0,就会将内核对象销毁,从内存空间中擦除。
下面写一个例子,三个线程,分别为如数1,2,3,要求每个线程输出10此,以1,2,3分别输出。
先定义三个信号量句柄:
HANDLE hsem1,hsem2,hsem3;
线程回调函数:
unsigned __stdcall threadFunA(void *)
{
for(int i = ; i < ; i++){
WaitForSingleObject(hsem1, INFINITE);//等待信号量
cout<<"first thread function"<<endl;
ReleaseSemaphore(hsem2, , NULL);//释放信号量2
}
return ;
}
该函数内部调用等待第一个信号量,如果获得资源,则打印日志,并且释放资源2
同样的道理,完成第二个,第三个线程回调函数
unsigned __stdcall threadFunB(void *)
{
for(int i = ; i < ; i++){
WaitForSingleObject(hsem2, INFINITE);//等待信号量
cout<<"second thread function"<<endl;
ReleaseSemaphore(hsem3, , NULL);//释放信号量3
}
return ;
} unsigned __stdcall threadFunC(void *)
{
for(int i = ; i < ; i++){
WaitForSingleObject(hsem3, INFINITE);//等待信号量
cout<<"third thread function"<<endl;
ReleaseSemaphore(hsem1, , NULL);//释放信号量
}
return ;
}
接下来在主函数创建三个线程,并且初始化第一个信号量的初始资源数为1,
第二个和第三个信号量初始资源数都是0,他们的最大资源数为1.
//创建信号量
hsem1 = CreateSemaphore(NULL, , , NULL);
hsem2 = CreateSemaphore(NULL, , , NULL);
hsem3 = CreateSemaphore(NULL, , , NULL); HANDLE hth1, hth2, hth3; //创建线程
hth1 = (HANDLE)_beginthreadex(NULL, , threadFunA, NULL, , NULL);
hth2 = (HANDLE)_beginthreadex(NULL, , threadFunB, NULL, , NULL);
hth3 = (HANDLE)_beginthreadex(NULL, , threadFunC, NULL, , NULL);
当线程调用完回调函数才能让主线程退出,linux系统对应的api为pthread_join(),
我们这里windows api为 WaitForSingleObject
//等待子线程结束
WaitForSingleObject(hth1, INFINITE);
WaitForSingleObject(hth2, INFINITE);
WaitForSingleObject(hth3, INFINITE);
最后释放线程的句柄和信号量的句柄
//一定要记得关闭线程句柄
CloseHandle(hth1);
CloseHandle(hth2);
CloseHandle(hth3);
CloseHandle(hsem1);
CloseHandle(hsem2);
CloseHandle(hsem3);
打印输出如下:
结果显示三个线程是按顺序输出的。所以信号量常用来同步线程。
源代码下载地址:http://download.csdn.net/detail/secondtonone1/9654799
我的公众号谢谢关注:
windows环境利用semophore机制进行线程同步的更多相关文章
- windows环境利用apache 配置虚拟主机
windows环境利用apache 配置虚拟主机 1.改动http.host #LoadModule vhost_alias_module modules/mod_vhost_alias.so #In ...
- 操作系统中的进程同步与Window中利用内核对象进行线程同步的关系
操作系统中为了解决进程间同步问题提出了用信号量机制,信号量可分为四种类型分别是互斥型信号量,记录型信号量,AND型信号量,信号量集. 互斥型信号量 互斥型信号量是资源数量为1的特殊的记录型信号量.表示 ...
- 在windows环境利用celery实现简单的任务队列
测试使用环境: 1.Python==3.6.1 2.MongoDB==3.6.2 3.celery==4.1.1 4.eventlet==0.23.0 Celery分为3个部分 (1)worker部分 ...
- Windows核心编程学习九:利用内核对象进行线程同步
注:源码为学习<Windows核心编程>的一些尝试,非原创.若能有助于一二访客,幸甚. 1.程序框架 #include "Queue.h" #include <t ...
- windows环境利用hexo+github搭建个人博客
一.下载安装Git 下载地址:https://gitforwindows.org/ 二.下载安装node.js 下载地址:https://nodejs.org/en/ 三.安装hexo 利用 npm ...
- windows核心编程---第七章 用户模式下的线程同步
用户模式下的线程同步 系统中的线程必须访问系统资源,如堆.串口.文件.窗口以及其他资源.如果一个线程独占了对某个资源的访问,其他线程就无法完成工作.我们也必须限制线程在任何时刻都能访问任何资源.比如在 ...
- 《windows核心编程系列》七谈谈用户模式下的线程同步
用户模式下的线程同步 系统中的线程必须访问系统资源,如堆.串口.文件.窗口以及其他资源.如果一个线程独占了对某个资源的访问,其他线程就无法完成工作.我们也必须限制线程在任何时刻都能访问任何资源.比如在 ...
- Java多线程 | 02 | 线程同步机制
同步机制简介 线程同步机制是一套用于协调线程之间的数据访问的机制.该机制可以保障线程安全.Java平台提供的线程同步机制包括: 锁,volatile关键字,final关键字,static关键字,以 ...
- C#并行编程(6):线程同步面面观
理解线程同步 线程的数据访问 在并行(多线程)环境中,不可避免地会存在多个线程同时访问某个数据的情况.多个线程对共享数据的访问有下面3种情形: 多个线程同时读取数据: 单个线程更新数据,此时其他线程读 ...
随机推荐
- 苹果全球营销高级副总裁Phil Schiller曾考虑炒掉长期创意代理商Media Arts Lab
来自<华尔街日报>消息,从去年开始,三星就利用广告来讽刺苹果产品.苹果全球营销高级副总裁菲尔•席勒(Phil Schiller)曾一度考虑炒掉该公司的长期创意代理商Media Arts L ...
- 曾经我是一个只会excel的数据分析师,直到我遇到了……
我是一个数据分析师. 准确来说我是一个当年只会excel数据透视表,就天不怕地不怕地来当数据分析师的人.当年的某一天,我的老板Q我: 小刘啊,我小姨子给了我一个全国市委书记的名单,你帮我看看,有什么规 ...
- Linux学习—导航文件系统
与windows相同,Linux操作系统也是以被称之为分层目录结构的方式来组织文件的.这意味着文件是以树形结构的目录中进行组织的,该树形结构目录可能包含文件和其他目录.文件系统的第一个目录叫做根目录, ...
- 20172314 蓝墨云课堂实践ASL
由于去跳啦啦操没有上课... 介绍 折半查找,又称作二分查找.这个查找的算法的特点,就是,要求数据要是有序的. 1 ,存储结构一定是顺序存储 2 ,关键字大小必须有序排列 然后,利用这组有序的数据之间 ...
- 基础算法学习2-dp
一.算法题: 最大子阵 给定一个n×m 的矩阵 A,求A 中的一个非空子矩阵,使这个子矩阵中的元素和最大.其中,A 的子矩阵指在 A 中行和列均连续的一部分.输入格式输入的第一行包含两个整数 n,m( ...
- 软工 · BETA 版冲刺前准备(团队)
软工 · BETA 版冲刺前准备(团队) 过去存在的问题 组员之间缺乏沟通,前后端缺乏沟通协作 组员积极性不高 基础知识不够扎实 手动整合代码效率过低 我们已经做了哪些调整/改进 通过会议加强组员之间 ...
- 0324操作系统cmd功能的扩展
需求:1.实现清屏功能 2.实现不区分大小写功能 3.添加功能能添加新的命令符 设计:1.使用system("cls")清屏. 2.使用strlwr()函数把大写都变成小写 3.( ...
- 使用 virt-install 创建虚拟机
使用 virt-install 创建虚拟机 virt-install --help 使用 qemu-kvm 创建虚拟机 介绍 1:命令路径:/usr/libexec/qemu-kvm 2:添加至环 ...
- 图文详解 IntelliJ IDEA 15 创建普通 Java Web 项目
第 1 部分:新建一个 Java Web Application 项目 File -> New -> Project…,请选择 Java EE 这个模块下的 Web Application ...
- 成功解决JSP和Servlet的中文乱码问题
表单提交时出现乱码: 在进行表单提交的时候,经常提交一些中文,自然就避免不了出现中文乱码的情况,对于表单来说有两种提交方式:get和post提交方式.所以请求的时候便有get请求和post请求.以前我 ...