[C++ 网络协议] Windows中的线程同步
目录
1. 用户模式(User mode)和内核模式(Kernal mode)
2. 用户模式的同步(CRITICAL_SECTION)
3. 内核模式同步
3.1 互斥量
3.2 信号量
3.3 事件对象
4. 实现Windows平台的多线程服务器端
1. 用户模式(User mode)和内核模式(Kernal mode)
Windows操作系统的运行方式是“双模式操作”:
- 用户模式:运行应用程序的基本模式,禁止访问物理设备,而且会限制访问的内存区域。
- 内核模式:操作系统运行时的模式,不仅不会限制访问的内存区域,而且访问的硬件设备也不会受损。
在应用程序的运行过程中,Windows操作系统会在用户模式和内核模式之间切换。比如说,在Windows中创建线程,虽然创造线程的请求是由应用程序的函数调用来完成的,但是线程是属于操作系统的,所以Windows会先从用户模式切换到内核模式,接着创建线程,分配资源,创建内核对象。
为什么要定义这两种模式?
答:为了提高安全性。因为应用程序在运行时如果发生错误,就可能会破坏操作系统的各种资源。尤其是C/C++可以进行指针运算,就很容易发生这种问题。而用户模式可以保护与操作系统有关的内存区域。所以应用程序在运行时发生错误也只会终止应用程序的运行,而不会终止操作系统。
那这两种模式只有优点吗?
答:不是,频繁的模式切换对系统而言也是一种负担,会影响性能。
2. 用户模式的同步(CRITICAL_SECTION)
用户模式的同步是在用户模式下的同步,这意味着,无需操作系统的帮助而在应用程序级别进行的同步 ,即无需进行内核模式的切换。
-
优点:速度快。
-
缺点:功能上存在局限性。
创建CRITICAL_SECTION对象:
#include<windows.h>void InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection //传入需要初始化的CRITICAL_SECTION对象//的地址值
);
CRITICAL_SECTION对象,不是内核对象。其只是一把进入临界区的“钥匙”。要进入临界区就提供这一把钥匙,离开临界区就要上交钥匙。
“销毁”CRITICAL_SECTION对象:
#include<windows.h>void DeleteCriticalSection(
LPCRITICAL_SECTION lpCriticalSection //传入需要销毁的CRITICAL_SECTION对象//的地址值
);
实际上这个函数并不是销毁CRITICAL_SECTION对象,而是销毁CRITICAL_SECTION对象使用过的(或与其相关的)资源。
上锁:
#include<windows.h>void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
解锁:
#include<windows.h>void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
3. 内核模式同步
内核模式的同步就是在内核模式下的同步。意味着都是通过操作系统的帮助下进行的线程同步。可以实现跨进程之间进行线程同步。(因为内核对象属于操作系统,而不属于进程)
- 优点:比用户模式提供的功能更多、可以指定超时,防止产生死锁
- 缺点:速度相对用户模式来说较慢
3.1 互斥量
互斥量对象是"auto-reset"模式的内核对象。([C++ 网络协议] Windows平台下的线程里有解释)
创建互斥量:
#include<windows.h>HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, //传递安全相关的配置信息,传NULL使用默认安全配置
BOOL bInitialOwner, //TRUE,创建的互斥量属于调用该函数的线程,//同时进入non-signaled状态//FALSE,创建处的互斥量对象不属于任何线程,//同时进入signaled状态
LPCTSTR lpName //用于命名互斥量对象,传NULL表示无名
);
成功返回创建的互斥量对象句柄
失败返回NULL
bInitialOwner参数:其实就是初始化互斥量的状态的值,为TRUE初始化为non-signaled状态。为FALSE初始化为signaled状态。
销毁互斥量:
#include<windows.h>BOOL CloseHandle(HANDLE hObject);
成功返回TRUE
失败返回FALSE
获取互斥量(上锁):
#include<windows.h>DWORD WaitForSingleObject(
HANDLE hHandle, //查看状态的内核对象句柄
DWORD dwMilliseconds //以1/1000秒为单位指定超时时间,传递INFINITE会阻塞住,//直到内核对象变为signaled状态
);
成功返回事件信息,事件信息:成功进入signaled状态返回WAIT_OBJECT_0,超时返回WAIT_TIMEOUT
失败返回WAIT_FAILED
这个函数就是“单个内核对象状态的查看”。所以可以判断出,线程是否被阻塞,看的是互斥量内核对象的状态。
释放互斥量(解锁):
#include<windows.h>BOOL ReleaseMutex(HANDLE hMutex);
成功返回TRUE,并使互斥量重新进入signaled状态
失败返回FALSE
例:
HANDLE mutex;
int main()
{mutex=CreateMutex(NULL,FALSE,NULL); //mutex初始化为signaled状态......
}unsigned WINAPI threadOne(void* arg)
{WaitForSingleObject(mutex,INFINITE); //mutex为signaled状态,则继续执行//临界区开始 //因为mutex是auto-reset模式的内核对象,所以mutex会变为non-signaled状态...... //临界区结束ReleaseMutex(mutex); //释放mutex将其设置为signaled状态
}unsigned WINAPI threadTwo(void* arg)
{WaitForSingleObject(mutex,INFINITE); //因为上面线程先执行,mutex变为了non-signaled状态,所以线程阻塞住,等待mutex的释放//临界区开始......//临界区结束ReleaseMutex(mutex);
}
3.2 信号量
创建信号量:
#include<windows.h>HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, //安全配置信息,默认安全设置传递NULL
LONG lInitialCount, //指定信号量的初始值,应>0,且<lMaximumCount
LONG lMaximumCount, //信号量的最大值,为1,则是二进制信号量(只能表示0或1)
LPCTSTR lpName //命名信号量对象,传NULL为无名
);
成功返回创建的信号量对象的句柄
失败返回NULL
销毁信号量:(和互斥量是一样的销毁句柄语句)
#include<windows.h>BOOL CloseHandle(HANDLE hObject);
成功返回TRUE
失败返回FALSE
通过信号量,判断线程是否阻塞:
#include<windows.h>DWORD WaitForSingleObject(
HANDLE hHandle, //查看状态的内核对象句柄
DWORD dwMilliseconds //以1/1000秒为单位指定超时时间,传递INFINITE会阻塞住,//直到内核对象变为signaled状态
);
成功返回事件信息,事件信息:成功进入signaled状态返回WAIT_OBJECT_0,超时返回WAIT_TIMEOUT
失败返回WAIT_FAILED
这个函数也是“单个内核对象状态的查看”。返回的同时信号量-1。
利用信号量为0时,进入non-signaled状态,大于0时,进入signaled状态,来进行同步。
释放信号量:
#include<windows.h>BOOL ReleaseSemaphore(
HANDLE hSemaphore, //传递需要释放的信号量
LONG lReleaseCount, //释放信号量会增加,这个参数指定要增加的值,超过最大值则不增加且返回FALSE
LPLONG lpPreviousCount //保存修改之前值得变量地址,不需要的话可传NULL
);
成功返回TRUE
失败返回FALSE
例:
HANDLE semOne;
HANDLE semTwo;int main()
{semOne=CreateSemaphore(NULL,0,1,NULL); //semOne为non-signaled状态semTwo=CreateSemaphore(NULL,1,1,NULL); //semTwo为signaled状态......
}unsigned WINAPI threadOne(void* arg)
{WaitForSingleObject(semTwo,INFINITE); //semTwo为signaled状态,继续执行,且semTwo-1变为non-signaled状态//临界区......//临界区ReleaseSemaphore(semOne,1,NULL); //semOne+1,变为signaled状态
}unsigned WINAPI threadTwo(void* arg)
{WaitForSingleObject(semOne,INFINITE); //通过上一个线程,semOne为signaled状态,开始执行,且semOne-1,变为non-signaled状态//临界区......//临界区ReleaseSemaphore(semTwo,1,NULL);
}
3.3 事件对象
基于事件对象的线程同步,与前两种同步方式有很大不同,因为事件对象创建时,可以选择是“auto-reset”模式还是“manual-reset”模式。这也是其进行同步的方式。
创建事件对象:
#include<windows.h>HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, //安全配置信息,默认安全设置传递NULL
BOOL bManualReset, //TRUE,创建manual-reset模式的事件对象//FALSE,创建auto-reset模式的事件对象
BOOL bInitialState, //TRUE,事件对象初始化为signaled状态//FALSE,事件对象初始化为non-signaled状态
LPCTSTR lpName //命名信号量对象,传NULL为无名
);
成功返回创建的事件对象句柄
失败返回NULL
销毁事件对象(销毁句柄语句):
#include<windows.h>BOOL CloseHandle(HANDLE hObject);
成功返回TRUE
失败返回FALSE
更改事件对象状态:
#include<windows.h>BOOL ResetEvent(HANDLE hEvent); //将事件对象设置为non-signaled状态
BOOL SetEvent(HANDLE hEvent); //将事件对象设置为signaled状态
成功返回TRUE
失败返回FALSE
例如:实现两个线程同时退出阻塞状态的情景。
HANDLE event;int main()
{event=CreateEvent(NULL,TRUE,FALSE,NULL); //将事件对象设置为mamual-reset模式,并初始化为non-signaled状态......SetEvent(event); //将事件对象设置为singnaled状态......
}unsigned WINAPI threadOne(void* arg)
{WaitForSingleObject(event,INFINITE); //阻塞,等待事件对象设置为singaled状态//临界区......//临界区
}unsigned WINAPI threadTwo(void* arg)
{WaitForSingleObject(event,INFINITE); //阻塞,等待事件对象设置为singaled状态//临界区......//临界区
}
4. 实现Windows平台的多线程服务器端
相关文章:
[C++ 网络协议] Windows中的线程同步
目录 1. 用户模式(User mode)和内核模式(Kernal mode) 2. 用户模式的同步(CRITICAL_SECTION) 3. 内核模式同步 3.1 互斥量 3.2 信号量 3.3 事件对象 4. 实现Windows平台的多线程服务器端 1. 用户模式(User mode)和内核模式(Kernal mode) Windows操作系统的运行方式是“…...
JavaScript 基础第三天笔记
JavaScript 基础第三天笔记 if 多分支语句和 switch的区别: 共同点 都能实现多分支选择, 多选1大部分情况下可以互换 区别: switch…case语句通常处理case为比较确定值的情况,而if…else…语句更加灵活,通常用于范围…...
NebulaGraph实战:3-信息抽取构建知识图谱
自动信息抽取发展了几十年,虽然模型很多,但是泛化能力很难用满意来形容,直到LLM的诞生。虽然最终信息抽取质量部分还是需要专家审核,但是已经极大的提高了信息抽取的效率。因为传统方法需要大量时间来完成数据清洗、标注和训练&am…...
一百八十二、大数据离线数仓完整流程——步骤一、用Kettle从Kafka、MySQL等数据源采集数据然后写入HDFS
一、目的 经过6个月的奋斗,项目的离线数仓部分终于可以上线了,因此整理一下离线数仓的整个流程,既是大家提供一个案例经验,也是对自己近半年的工作进行一个总结。 二、项目背景 项目行业属于交通行业,因此数据具有很…...
工具篇 | H2数据库的使用和入门
引言 1.1 H2数据库概述 1.1.1 定义和特点 H2数据库是一款以 Java编写的轻量级关系型数据库。由于其小巧、灵活并且易于集成,H2经常被用作开发和测试环境中的便利数据库解决方案。除此之外,H2也适合作为生产环境中的嵌入式数据库。它不仅支持标准的SQL…...
PHP脚本导出MySQL数据库
背景:有时候需要同步数据库的表结构和部分数据,同步全表数据非常大,也不适合。还有一个种办法是使用数据库的dump命令执行备份,无法进入服务器?没有权限怎么办? 这里只要能访问服务器中的 information_sch…...
生成随机单据号
背景:全局生成4位字符2222-9ZZ9 实现方式: 使用redis的原子自增 google的retry保证,生成4位数 1、pom <dependency><groupId>com.github.rholder</groupId><artifactId>guava-retrying</artifactId><v…...
【计算机网络笔记五】应用层(二)HTTP报文
HTTP 报文格式 HTTP 协议的请求报文和响应报文的结构基本相同,由四部分组成: ① 起始行(start line):描述请求或响应的基本信息;② 头部字段集合(header):使用 key-valu…...
安装Python3.x--Windows
1 下载安装包 确定安装是干什么,要下哪个版本(如果是配置项目环境,最好按项目需求的版本来装) 1.1 官网链接 https://www.python.org 最新版本 指定版本 2 安装说明 点击下载exe,运行自定义安装路径,下…...
坐标休斯顿,TDengine 受邀参与第九届石油天然气数字化大会
美国中部时间 9 月 14 日至 15 日,第九届石油天然气数字化大会在美国德克萨斯州-休斯顿-希尔顿美洲酒店举办。本次大会汇聚了数百名全球石油天然气技术高管及众多极具创新性的数据技术方案商,组织了上百场硬核演讲,技术专家与行业从业者共聚一…...
labview 混合信号图 多曲线分组
如果你遇到了混合信号图 多曲线分组显示的问题,本文能给你帮助。 在文章的最好,列出了参考程序下载链接。 一个混合信号图中可包含多个绘图区域。 但一个绘图区域仅能显示数字曲线或者模拟曲线之一,无法兼有二者。 以下显示的分两组&#…...
客户端负载均衡_负载均衡策略
以前的Ribbon有多种负载均衡策略 RandomRule - 随性而为 解释: 随机 RoundRobinRule - 按部就班 解释: 轮询 RetryRule - 卷土重来 解释: 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试。 Weigh…...
使用Python+Flask/Moco框架/Fiddler搭建简单的接口Mock服务
一、Mock测试 1、介绍 mock:就是对于一些难以构造的对象,使用虚拟的技术来实现测试的过程mock测试:在测试过程中,对于某些不容易构造或者不容易获取的对象,可以用一个虚拟的对象来代替的测试方法接口mock测试&#x…...
【Vue】Mock.js介绍和使用与首页导航栏左侧菜单搭建
目录 一、Mock.js 1.1 mockjs介绍 1.2 mock.js安装与配置 1.2.1 安装mock.js 1.2.2 引入mock.js 1.3 mock.js的使用 1.3.1 准备模拟数据 1.3.2 定义拦截路由 1.3.3 测试 二、首页导航栏左侧菜单搭建 2.1 自定义界面组件 (完整代码) 2.2 配置路由 2.3 组件显示折叠和…...
离散小波变换(概念与应用)
目录 概念光伏功率预测中,如何用离散小波变换提取高频特征概念 为您简单地绘制一些示意图来描述离散小波变换的基本概念。但请注意,这只是一个简化的示意图,可能不能完全捕捉到所有的细节和特性。 首先,我将为您绘制一个简单的小波函数和尺度函数的图像。然后,我会提供一…...
代码随想录day49:动态规划part10
121.买卖股票的最佳时机 贪心: class Solution { public:int maxProfit(vector<int>& prices) {int low INT_MAX;int result 0;for (int i 0; i < prices.size(); i) {low min(low, prices[i]); // 取最左最小价格result max(result, prices[i…...
fofa搜索使用
fofa搜索使用 文章目录 fofa搜索使用网站fofa搜索语法多条件查询 网站fofa https://fofa.info/搜索语法 1.title”beijing”从标题中搜索“北京2.headerQ"thinkphp”从http响应头中搜索“thinkphp3.body”管理后台”从html正文中搜索“管理后台4.domain”163.com”从子域…...
husky+lint-staged+eslint+prettier+stylelint+commitlint
概念: husky,暴露出git的hook钩子,在这些钩子执行一些命令,lint-staged,只在git的暂存区有修改的文件进行lint操作,执行一些校验脚本eslint,prettier,styelint有npm包还有对应的scode插件,其中npm包是用于执行那些诸如入eslint --fix "src/**/*.{js,jsx,…}"的脚本命…...
图像处理与计算机视觉--第四章-图像滤波与增强-第一部分
目录 1.灰度图亮度调整 2.图像模板匹配 3.图像裁剪处理 4.图像旋转处理 5.图像邻域与数据块处理 学习计算机视觉方向的几条经验: 1.学习计算机视觉一定不能操之过急,不然往往事倍功半! 2.静下心来,理解每一个函数/算法的过程和精髓&…...
【go】字符串切片与字符串出入数据库转化
文章目录 需求代码入库出库 需求 将请求数据存入数据库与从数据库读取数据返回在出库不使用反序列化情况下 请求结构体 type NoticegroupsCreateReq struct {Name string json:"name" binding:"required"UserIds []string json:"user_ids…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
