当前位置: 首页 > news >正文

【Windows】线程同步之信号量(Semaphores)

概述: semaphores 的说明和使用

微软官方文档:

  • Semaphore Objects - Win32 apps | Microsoft Learn

Semaphores是解决各种 producer/consumer问题的关键要素。这种问题会存有一个缓冲区,可能在同一时间内被读出数据或被写入数据。

理论可以证明,mutex 是 semaphore 的一种退化。如果你产生一个semaphore 并令最大值为1,那就是一个 mutex。也因此, mutex又常被称为binary semaphore。在许多系统中, semaphores 常被使用, 因为 mutexes可能并不存在。在Win32中semaphores 被使用的情况就少得多,因为 mutex 存在的缘故。

创建 semaphore

createSemaphoreA 函数 (winbase.h) - Win32 apps | Microsoft Learn

HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpAttributes,	// 安全属性, 可以设置NULLLONG lInitialCount,	// 初始值, [0, lMaximumCount]LONG lMaximumCount,	// 最大值, 这也就是在同一时间内能够锁住semaphore之线程的最多个数LPCTSTR lpName		// 名称, 其他线程或进程可以根据名称引用该信号量; NULL则产生无名称信号量
);

如果成功就传回一个handle, 否则传回NULL. 不论哪一种情况,GetLastError()都会传回一个合理的结果. 如果指定的semaphore名称已经存在,则该函数还是成功的, GetLastError()会传回ERROR_ALREADY_EXISTS.

获得 semaphore

通过信号量名,获得信号量对象句柄

OpenSemaphoreW function (synchapi.h) - Win32 apps | Microsoft Learn

HANDLE OpenSemaphoreW([in] DWORD   dwDesiredAccess, // 访问权限,一般传入 SEMAPHORE_ALL_ACCESS [in] BOOL    bInheritHandle, // 信号量句柄继承性,一般传入TRUE即可[in] LPCWSTR lpName // 名称,不同进程中个线程可以通过名称来确保它们访问同一个信号量
);

semaphore的现值代表的意义是目前可用的资源数, 如果semaphore的现值为1, 表示还有一个锁定动作可以成功; 如果现值为5, 就表示还有五个锁定动作可以成功. 每当一个锁定动作成功, semaphore的现值就会减1. 你可以使用任何一种 Wait() 函数(例如 WaitForSingleObject() )要求锁定一个semaphore. 因此, 如果semaphore的现值不为0, Wait() 函数会立刻返回.
一个线程可以反复调用 Wait() 函数以产生新的锁定. 这和mutex绝不相同:拥有mutex的线程不论再调用多少次 Wait() 函数, 也不会被阻塞住。
一旦semaphore的现值降到0, 就表示资源已经耗尽. 此时, 任何线程如果调用Wait…()函数, 必然要等待, 直到某个锁定被解除为止.

解除 semaphore

释放信号量

ReleaseSemaphore function (synchapi.h) - Win32 apps | Microsoft Learn

注:传入的句柄必须有 SEMAPHORE_MODIFY_STATE 权限,参考 同步对象安全性和访问权限 - Win32 apps | Microsoft Learn

BOOL ReleaseSemaphore([in]            HANDLE hSemaphore, // 信号量的句柄[in]            LONG   lReleaseCount, // 表示增加个数,必须大于0且不超过最大资源数量[out, optional] LPLONG lpPreviousCount // 可以用来传出先前的资源计数,设为NULL表示不需要传出
);

ReleaseSemaphore函数会触发WaitForSingleObject函数。ReleaseSemaphore函数用于释放一个信号量对象的计数,而WaitForSingleObject函数用于等待一个信号量对象的计数。当ReleaseSemaphore函数被调用时,它会将信号量对象的计数增加,并且如果有一个线程正在等待这个信号量对象的计数,那么这个线程就会被唤醒。因此,ReleaseSemaphore函数会触发WaitForSingleObject函数。

补充说明

为什么 semaphore 要有一个初值

CreateSemaphore()的第二个参数是lInitialCount, 它的存在理由和CreateMutex()的bInitialOwner参数的存在理由是一样的. 如果你把初值设定为0, 你的线程就可以在产生semaphore之后进行所有必要的初始化工作. 待初始化工作完成后, 调用 ReleaseSemaphore()就可以把现值增加到其最大可能值.

Demo 多线程同步

#include <stdio.h>  
#include <process.h>  
#include <windows.h>  
long g_nNum;
unsigned int __stdcall Fun(void* pPM);
const int THREAD_NUM = 10;
//信号量与关键段  
HANDLE            g_hThreadParameter;
CRITICAL_SECTION  g_csThreadCode;
int main()
{printf("     经典线程同步 信号量Semaphore\n");printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");//初始化信号量和关键段  g_hThreadParameter = CreateSemaphore(NULL, 0, 1, NULL);//当前0个资源,最大允许1个同时访问  InitializeCriticalSection(&g_csThreadCode);HANDLE  handle[THREAD_NUM];g_nNum = 0;int i = 0;while (i < THREAD_NUM){handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);WaitForSingleObject(g_hThreadParameter, INFINITE);//等待信号量>0  ++i;}WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);//销毁信号量和关键段  DeleteCriticalSection(&g_csThreadCode);CloseHandle(g_hThreadParameter);for (i = 0; i < THREAD_NUM; i++)CloseHandle(handle[i]);return 0;
}
unsigned int __stdcall Fun(void* pPM)
{int nThreadNum = *(int*)pPM;ReleaseSemaphore(g_hThreadParameter, 1, NULL);//信号量++  Sleep(50);//some work should to do  EnterCriticalSection(&g_csThreadCode);++g_nNum;Sleep(0);//some work should to do  printf("线程编号为%d  全局资源值为%d\n", nThreadNum, g_nNum);LeaveCriticalSection(&g_csThreadCode);return 0;
}

相关文章:

【Windows】线程同步之信号量(Semaphores)

概述&#xff1a; semaphores 的说明和使用 微软官方文档&#xff1a; Semaphore Objects - Win32 apps | Microsoft Learn Semaphores是解决各种 producer/consumer问题的关键要素。这种问题会存有一个缓冲区&#xff0c;可能在同一时间内被读出数据或被写入数据。 理论可以证…...

二叉树问题——前中后遍历数组构建二叉树

摘要 利用二叉树的前序&#xff0c;中序&#xff0c;后序&#xff0c;有序数组来构建相关二叉树的问题。 一、构建二叉树题目 105. 从前序与中序遍历序列构造二叉树 106. 从中序与后序遍历序列构造二叉树 889. 根据前序和后序遍历构造二叉树 617. 合并二叉树 226. 翻转二…...

Java保留n位小数的方法(超简洁)

要输出double类型保留n位小数的几种方法如下&#xff1a; 我们以保留6位小数为例 方法一&#xff1a;使用DecimalFormat类 import java.text.DecimalFormat;public class Main {public static void main(String[] args) {double number 3.141592653589793;DecimalFormat df …...

JavaEE-博客系统1(数据库和后端的交互)

本部分内容包括网站设计总述&#xff0c;数据库和后端的交互&#xff1b; 数据库操作代码如下&#xff1a; -- 编写SQL完成建库建表操作 create database if not exists java_blog_system charset utf8; use java_blog_system; -- 建立两张表&#xff0c;一个存储博客信息&am…...

【unity/vufornia】Duplicate virtual buttons with name.../同一个ImageTarget上多个按钮失灵

问题&#xff1a;在同一个ImageTarget上添加多个按钮时无法触发对应按钮的事件。 解决过程&#xff1a; 1.查看报错&#xff1a;“Duplicate virtual buttons with name...”这一行&#xff0c;顾名思义&#xff0c;命名重复。 2.英文搜索到以下文章&#xff0c;应该在inspe…...

Apache ActiveMQ 远程代码执行漏洞复现(CNVD-2023-69477)

Apache ActiveMQ 远程代码执行RCE漏洞复现&#xff08;CNVD-2023-69477&#xff09; 上周爆出来的漏洞&#xff0c;正好做一下漏洞复现&#xff0c;记录一下 1.漏洞描述 ​ Apache ActiveMQ 中存在远程代码执行漏洞&#xff0c;具有 Apache ActiveMQ 服务器TCP端口&#xff…...

项目管理-科学管理基础-线性规划介绍及例题

项目管理中的线性规划是什么? 在项目管理中,线性规划是一种数学建模和优化技术,用于解决资源分配和进度规划的问题。线性规划的目标是在给定的资源限制下,找到最佳的资源分配方案,以满足项目的需求并优化特定的目标,如成本最小化或时间最短化。 线性规划的基本元素包括…...

如何利用自定义数据对象(元数据)实现全场景身份数据治理

在数字化时代背景下&#xff0c;5G、云计算、大数据、物联网、人工智能等技术的发展&#xff0c;为企业数据管理提供了基础技术支撑。数字化浪潮推动企业快速升级迭代&#xff0c;在数据管理和数字化转型过程中&#xff0c;企业内部的数据情况常常错综复杂&#xff0c;并伴随着…...

腾讯云轻量级服务器哪个镜像比较好?

腾讯云轻量应用服务器镜像是什么&#xff1f;镜像就是操作系统&#xff0c;轻量服务器镜像系统怎么选择&#xff1f;如果是用来搭建网站腾讯云百科txybk.com建议选择选择宝塔Linux面板腾讯云专享版&#xff0c;镜像系统根据实际使用来选择&#xff0c;腾讯云百科来详细说下腾讯…...

SC密封件的材料成分

SC密封件也称为轴密封件&#xff0c;是许多机械系统中的关键组件&#xff0c;提供防止润滑剂泄漏和污染物进入的屏障。但SC密封件是由什么材料制成的呢? SC密封型材由带有橡胶涂层的单个金属保持架和带有集成弹簧的主密封唇组成。这种材料的组合为密封件提供了其基本特性&…...

常用 sqlite3 命令

本次将向您讲解 SQLite 编程人员所使用的简单却有用的命令。这些命令被称为 SQLite 的点命令&#xff0c;这些命令的不同之处在于它们不以分号 ; 结束。 让我们在命令提示符下键入一个简单的 sqlite3 命令&#xff0c;在 SQLite 命令提示符下&#xff0c;您可以使 用各种 …...

SpringMVC Day 08 : 文件上传下载

前言 文件上传和下载是 Web 开发中的重要环节&#xff0c;但它们往往不那么容易实现。幸运的是&#xff0c;Spring MVC 提供了一套简单而又强大的解决方案&#xff0c;让我们可以专注于业务逻辑&#xff0c;而不必过多关注底层的文件处理细节。 在本篇博客中&#xff0c;我们…...

【热带气旋】基本介绍:定义、标准、结构等

热带气旋基本介绍 热带气旋&#xff08;Tropical Cyclone, TC&#xff09;1 热带气旋定义2 热带气旋标准2.1 热带低压&#xff08;Tropical Depression&#xff09;2.2 热带风暴&#xff08;Tropical storm&#xff09;2.3 强热带风暴&#xff08;Severe tropical storm&#x…...

ue5 右击.uproject generator vs project file 错误

出现如下错误 Unable to find valid 14.31.31103 C toolchain for VisualStudio2022 x64 就算你升级了你的 vs installer 也不好使 那是因为 在C:\Users\{YourUserName}\AppData\Roaming\Unreal Engine\UnrealBuildTool\BuildConfiguration.xml 这个缓存配置文件中写死了 14…...

0X01

打开题目 点了几下跳出一个新的页面 点击secret 在上一个页面查看源代码&#xff0c;出现action.php然后点击之后就会在地址栏里面出现end.php 抓包看看&#xff0c;出现secr3t.php huidao开始的页面&#xff0c;访问看看 这是一个PHP脚本&#xff0c;以HTML标签开头。该脚本包…...

centos7 配置搭建 wordpress 博客

环境配置 系统&#xff1a;centos7 CPU:2核 内存&#xff1a;4G 硬盘&#xff1a;40G 一、登录云服务器器 1.单击实例--实例名称 2. 选择安全组页签&#xff0c;单击安全组操作列的管理规则&#xff0c; 3.在入方向添加需要放行的端口。本教程中&#xff0c;在安全组入方向…...

掌握Android自定义View与独家优化技巧

在Android应用开发中&#xff0c;自定义View是一种强大的工具&#xff0c;可以帮助你创建独特的用户界面元素。本文将详细介绍如何创建自定义View&#xff0c;并提供优化技巧&#xff0c;以确保你的自定义View在性能和用户体验方面表现出色。 什么是自定义View 自定义View是A…...

【T3】彻底关闭服宝

【问题描述】 畅捷通T3登录后&#xff0c; 右下角会出现服宝窗口&#xff0c;需要手工退出。 但是每次重新登录账套后都会出现&#xff0c;非常烦&#xff1b;并且界面空白。 【解决方法】 在软件的安装目录下\UFSMART\Portal&#xff0c;找到【url.ini】文件。 用记事本打开…...

P2359 三素数数 , 线性dp

题目背景 蛟川书院的一道练习题QAQ 题目描述 如果一个数的所有连续三位数字都是大于100的素数&#xff0c;则该数称为三素数数。比如113797是一个6位的三素数数。 输入格式 一个整数n&#xff08;3 ≤ n ≤ 10000&#xff09;&#xff0c;表示三素数数的位数。 输出格式 …...

【c语言】用C语言设计一个环形缓冲区。当环形缓冲区有一半占用未处理时,提示使用了50%.

InsCode AI创作助手 #include <stdio.h> #include <stdlib.h>#define BUFFER_SIZE 10int buffer[BUFFER_SIZE]; // 环形缓冲区数组 int readIndex 0; // 缓冲区读取索引 int writeIndex 0; // 缓冲区写入索引 int count 0; // 缓冲区占用计数器void enqueue(in…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...