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

C- 使用原子变量实现信号量

信号量

信号量(Semaphore)是并发编程中的一个核心同步原语,它在多进程和多线程环境下被设计用来协调不同的执行单元,确保它们在对共享资源的访问上达到同步和互斥。信号量内部维护一个计数器,该计数器的初始值可以被视为可用资源的数量。当一个进程或线程试图“获取”一个信号量时,该计数器会递减;当它“释放”信号量时,计数器则递增。如果计数器的值达到零,任何试图获取信号量的操作都会被阻塞,直至其他进程或线程释放资源。

信号量通常可以分为两大类:命名信号量(Named Semaphores)和无名信号量(Unnamed Semaphores)。命名信号量是通过一个独特的标识符,在系统级别进行识别的,通常与文件系统上的某个文件关联。这使得不同的进程可以通过这一标识符来定位和操作同一个信号量。而无名信号量主要存在于进程的内存地址空间中,通常用于进程内的线程同步。由于无名信号量仅存在于进程的内存中,因此它们的生命周期与包含它们的进程相同。

为了有效利用信号量,开发者需要深入理解其工作机制和相关的API调用,确保在并发和竞争条件下实现正确、高效的资源访问控制。

实现信号量

实现信号量仅使用原子变量是相对复杂的。以下是一个简单的信号量实现,使用 C11 的 atomic_int

#include <stdio.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <pthread.h>typedef struct {atomic_int value;
} AtomicSemaphore;void AtomicSemaphore_init(AtomicSemaphore* sem, int initial) {atomic_store(&sem->value, initial);
}void AtomicSemaphore_wait(AtomicSemaphore* sem) {int expected;do {while ((expected = atomic_load(&sem->value)) <= 0) {// busy-wait/spin until value is greater than 0}} while (!atomic_compare_exchange_weak(&sem->value, &expected, expected - 1));
}void AtomicSemaphore_post(AtomicSemaphore* sem) {atomic_fetch_add(&sem->value, 1);
}void* test_func(void* arg) {AtomicSemaphore* sem = (AtomicSemaphore*)arg;AtomicSemaphore_wait(sem);printf("Thread %ld acquired the semaphore!\n", pthread_self());AtomicSemaphore_post(sem);return NULL;
}int main() {AtomicSemaphore sem;AtomicSemaphore_init(&sem, 1);  // Initial value set to 1pthread_t threads[10];for (int i = 0; i < 10; i++) {pthread_create(&threads[i], NULL, test_func, &sem);}for (int i = 0; i < 10; i++) {pthread_join(threads[i], NULL);}return 0;
}

注意:

  1. 这个简单的信号量实现使用了"忙等待"或自旋,这可能会导致性能问题,尤其是在高度竞争的情况下。

  2. atomic_compare_exchange_weak 函数尝试将 sem->value 更新为 expected - 1,只有当 sem->value 的当前值与 expected 匹配时才会这样做。如果不匹配,函数将返回 false,并在 expected 中设置当前的 sem->value

  3. 在真实环境中,可能需要考虑使用更复杂的策略(例如,当信号量值为0时,线程进入休眠状态而不是持续自旋)。

  4. 虽然这个实现提供了原子操作的信号量,但它不是传统的信号量,因为它并不提供线程阻塞功能。这意味着当信号量的值为0时,线程将持续自旋,直到它可以获取信号量。

相关文章:

C- 使用原子变量实现信号量

信号量 信号量&#xff08;Semaphore&#xff09;是并发编程中的一个核心同步原语&#xff0c;它在多进程和多线程环境下被设计用来协调不同的执行单元&#xff0c;确保它们在对共享资源的访问上达到同步和互斥。信号量内部维护一个计数器&#xff0c;该计数器的初始值可以被视…...

Pytorch与Onnx的转换与推理

Open Neural Network Exchange&#xff08;ONNX&#xff0c;开放神经网络交换&#xff09;格式&#xff0c;是一个用于表示深度学习模型的标准&#xff0c;可使模型在不同框架之间进行转移。 一、pytorch模型保存/加载 有两种方式可用于保存/加载pytorch模型 1&#xff09;文件…...

Linux权限详解

文章目录 1. shell命令及运行原理2. Linux权限的概念&#xff08;1&#xff09;用户种类&#xff08;2&#xff09;切换用户&#xff08;3&#xff09;命令提权 3. Linux权限管理&#xff08;1&#xff09;文件访问者的分类&#xff08;人&#xff09;&#xff08;2&#xff09…...

基于react18+arco+zustand通用后台管理系统React18Admin

React-Arco-Admin轻量级后台管理系统解决方案 基于vite4构建react18后台项目ReactAdmin。使用了reactarco-designzustandbizcharts等技术架构非凡后台管理框架。支持 dark/light主题、i18n国际化、动态路由鉴权、3种经典布局、tabs路由标签 等功能。 技术框架 编辑器&#xff…...

BAT031:按列表名单将路径a下的文件夹批量剪切到路径b

引言&#xff1a;编写批处理程序&#xff0c;实现按列表名单将路径a下的文件夹批量剪切到路径b。 一、新建Windows批处理文件 参考博客&#xff1a; CSDNhttps://mp.csdn.net/mp_blog/creation/editor/132137544 二、写入批处理代码 1.右键新建的批处理文件&#xff0c;点击…...

随机专享记录第一话 -- RustDesk的自我搭建和使用

1.介绍 RustDesk是继TeamView、向日葵等远程桌面软件后的新起之秀,最主要的是开源的可自己搭建中继服务。相比于公共服务器,连接一次等待的时间要多久,用过TeamView的都知道,而且还是免费的,不像某些远程搞各种个人证书,各种登录设备限制! 先看看软件图,这是待连接界…...

【数据库】拼接字段 使用别名

拼接字段 使用别名 e . g . e.g. e.g. Vendors 表包含供应商名和电话信息&#xff0c;name 和 mobile&#xff1b;需要输出这两个属性的值的组合作为供应商的基本信息组合。 SELECT concat(name, _, mobile) FROM Vendors; -- 语句通过 MySQL 环境下测试&#xff0c;其他 DBMS…...

Golang设计22种模式

什么是设计模式 设计模式是面向对象软件的设计经验,是通常设计问题的解决方案。每一种设计模式系统的命名、解释和评价了面向对象中一个重要的和重复出现的设计。 设计模式的分类 创建模式 - 用来帮助我们创建对象的 工厂模式 (Factory Pattern)抽象工厂模式 (Abstract F…...

MMKV(3)

使用时遇到的问题 在项目的构建配置文件&#xff08;如 Gradle 或 Maven&#xff09;中添加相应的依赖项。 MMKV 是一个键值存储库&#xff0c;它存储的是原始的字节数组数据。需要存储和检索复杂的对象或数据结构&#xff0c;需要自行进行序列化和反序列化操作。可以使用任何…...

vivado报错警告之[Vivado 12-1017] Problems encountered:

文章目录 方法一方法二方法三&#xff08;作者最终解决&#xff09; 我们对vivado 的程序进行综合(Run Synthesis)时&#xff0c;可能会出现[Vivado 12-1017] Problems encountered: 1. Failed to delete one or more files in run directory的一个警告信息&#xff0c;导致我们…...

基于springboot汽车租赁系统

功能如下图所示 摘要 Spring Boot汽车租赁系统的设计旨在满足不断增长的租车市场需求&#xff0c;并通过简化开发和部署流程来提供方便的租车解决方案。系统采用了现代化的架构&#xff0c;主要基于以下技术栈&#xff1a; Spring Boot&#xff1a;作为后端的核心框架&#xff…...

C++禁用赋值操作符

1.禁用赋值操作符 在C中&#xff0c;void operator(const ClassName&) delete; 是一种特殊的语法&#xff0c;用于明确地禁止赋值操作符&#xff08;assignment operator&#xff09;的默认实现或自定义实现。 这通常用于防止类的实例被意外赋值。通过明确地删除赋值操作…...

小程序的数据驱动和vue的双向绑定有何异同?

小程序的数据驱动和Vue的双向绑定有以下异同之处&#xff1a; 异同点&#xff1a; 数据驱动&#xff1a;小程序的数据驱动是指通过编写数据绑定的代码&#xff0c;将数据与视图进行关联&#xff0c;当数据发生变化时&#xff0c;视图会自动更新。而Vue的双向绑定则是一种特殊的…...

Nvm管理NodeJs版本

文章目录 Nvm管理NodeJs版本一、前言1.简介2.环境 二、正文1.卸载NodeJs2.安装Nvm3.配置国内镜像4.Nvm使用5.其它1&#xff09;报错12&#xff09;报错2 Nvm管理NodeJs版本 一、前言 1.简介 Node Version Manager&#xff08;nvm&#xff09;可通过命令行快速安装和使用不同…...

阿里云国际站服务器开放端口详解!!

在互联网技术发展的今天&#xff0c;服务器扮演着至关重要的角色。作为云服务供给商&#xff0c;阿里云服务器供给了安稳、高效的服务&#xff0c;而敞开端口则是阿里云服务器功能的重要体现。本文将详细解读阿里云服务器敞开端口的意义、实现办法以及其带来的优点。 一、阿里云…...

【自动化测试入门】用Airtest - Selenium对Firefox进行自动化测试(0基础也能学会)

1. 前言 本文将详细介绍如何使用AirtestIDE驱动Firefox测试&#xff0c;以及脱离AirtestIDE怎么驱动Firefox&#xff08;VScode为例&#xff09;。看完本文零基础小白也能学会Firefox浏览器自动化测试&#xff01;&#xff01;&#xff01; 2. 如何使用AirtestIDE驱动Firefox…...

Python 爬虫入门:常见工具介绍

接着我的上一篇文章《网页爬虫完全指南》&#xff0c;这篇文章将涵盖几乎所有的 Python 网页爬取工具。我们从最基本的开始讲起&#xff0c;逐步涉及到当前最前沿的技术&#xff0c;并且对它们的利弊进行分析。 当然&#xff0c;我们不能全面地介绍每个工具&#xff0c;但这篇…...

uniGUI文件操作

一.文件上传TUniFileUploadButton TUniFileUploadButton主要属性&#xff1a; Filter: 文件类型过滤&#xff0c;有图片image/* audio/* video/*三种过滤 MaxAllowedSize: 设置文件最大上传尺寸&#xff1b; Message&#xff1a;标题以及消息文本&#xff0c;可翻译成中文…...

Python多进程之分享(multiprocessing包)

threading和multiprocessing (可以阅读Python多线程与同步) multiprocessing包是Python中的多进程管理包。与threading.Thread类似&#xff0c;它可以利用multiprocessing.Process对象来创建一个进程。该进程可以运行在Python程序内部编写的函数。该Process对象与Thread对象的…...

【试题028】C语言关于逻辑与的短路例题

1.题目&#xff1a;设inta1,b;&#xff0c;执行b0&&(a);后&#xff0c;变量a的值是&#xff1f; 2.代码解析&#xff1a; #include <stdio.h> int main() {//设inta1,b;执行b0&&(a);后&#xff0c;变量a的值是?int a 1, b;printf("表达式的值是…...

GG3M 项目贝叶斯更新与决策数学的具体落地应用

GG3M贝叶斯决策体系&#xff1a;基于贾子公理的跨领域反熵增智慧决策应用摘要&#xff1a; GG3M项目以贾子公理体系为底层支撑&#xff0c;独创“事实层-模型层-元模型层”层级化贝叶斯架构&#xff0c;实现了从参数优化到认知框架迭代的范式突破。该体系以系统长期反熵增演化为…...

如何为Whisper ASR Webservice开发自定义引擎和插件

如何为Whisper ASR Webservice开发自定义引擎和插件 【免费下载链接】whisper-asr-webservice OpenAI Whisper ASR Webservice API 项目地址: https://gitcode.com/gh_mirrors/wh/whisper-asr-webservice Whisper ASR Webservice是一个基于OpenAI Whisper的语音识别服务…...

OpCore-Simplify:开源系统硬件适配的技术突破与架构革新

OpCore-Simplify&#xff1a;开源系统硬件适配的技术突破与架构革新 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 在开源系统定制领域&#xff0c;硬…...

Qwen3-14B快速上手教程:命令行推理+参数详解(temperature/max_length)

Qwen3-14B快速上手教程&#xff1a;命令行推理参数详解&#xff08;temperature/max_length&#xff09; 1. 镜像概述与环境准备 Qwen3-14B是通义千问推出的大语言模型&#xff0c;本教程将指导您快速上手使用专为RTX 4090D 24GB显存优化的私有部署镜像。这个镜像已经预装了所…...

告别枯燥Loading!聊聊Android骨架屏的‘心理战术’与设计取舍

告别枯燥Loading&#xff01;Android骨架屏的UX心理学与架构设计博弈 当用户盯着那个旋转的小圆圈超过3秒时&#xff0c;他们的耐心就像沙漏里的沙子一样快速流失。但有趣的是&#xff0c;如果换成骨架屏——那些跳动的灰色块——同样的3秒等待却变得可以接受。这不是魔法&…...

BeanUtils vs MapStruct:Java对象拷贝工具选型指南(附性能对比测试)

BeanUtils vs MapStruct&#xff1a;Java对象拷贝工具深度评测与选型指南 在Java开发中&#xff0c;对象属性拷贝是几乎每个项目都会遇到的常见需求。从简单的DTO转换到复杂的领域模型映射&#xff0c;选择高效、稳定的拷贝工具直接影响代码质量和系统性能。本文将深入对比Apac…...

SenseVoice-small实战教程:导出SRT/VTT字幕文件用于Premiere剪辑

SenseVoice-small实战教程&#xff1a;导出SRT/VTT字幕文件用于Premiere剪辑 你是不是经常遇到这样的烦恼&#xff1f;录了一段视频&#xff0c;或者拿到一段会议录音&#xff0c;想要给它配上精准的字幕&#xff0c;却发现自己要花几个小时去听写、校对、打时间轴&#xff1f…...

Hugo Coder性能优化技巧:提升网站加载速度的7个方法

Hugo Coder性能优化技巧&#xff1a;提升网站加载速度的7个方法 【免费下载链接】hugo-coder A minimalist blog theme for hugo. 项目地址: https://gitcode.com/gh_mirrors/hu/hugo-coder 如果你正在使用Hugo Coder主题来构建个人博客或开发者网站&#xff0c;那么网站…...

HCPL-0700-000E,低输入电流、高增益且与高安全隔离性能的光耦

型号介绍今天我要向大家介绍的是 Broadcom 的光耦——HCPL-0700-000E。它的内部结构就像一个高效的“信号转换站”&#xff0c;结合了一个发光二极管和一个集成的高增益光子探测器。光电二极管和输出级采用独立引脚设计&#xff0c;当输入端接收到电流时&#xff0c;LED 会发出…...

3大场景解放双手:SteamShutdown智能管理下载与自动控制电脑的完整方案

3大场景解放双手&#xff1a;SteamShutdown智能管理下载与自动控制电脑的完整方案 【免费下载链接】SteamShutdown Automatic shutdown after Steam download(s) has finished. 项目地址: https://gitcode.com/gh_mirrors/st/SteamShutdown 你是否曾在深夜开启游戏下载后…...