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

C语言多线程同步实战:从竞态到协同的四种武器

1. 多线程售票问题竞态条件的典型场景想象一下春运期间的火车站售票窗口4个售票员同时售卖20张车票。如果缺乏有效的管理机制很可能出现同一张票被重复售卖或者票数统计出错的情况。这个场景完美模拟了多线程编程中最经典的竞态条件问题。在实际编码中我们常常会遇到类似的情况。比如下面这个模拟售票的C语言程序#includestdio.h #includestdlib.h #includepthread.h int ticket_sum 20; // 总票数 void *sell_ticket(void *arg) { for(int i0; i20; i) { if(ticket_sum 0) { sleep(1); // 模拟售票耗时 printf(%u 卖出第%d张票\n, pthread_self(), 20-ticket_sum1); ticket_sum--; } } return NULL; } int main() { pthread_t tids[4]; for(int i0; i4; i) { pthread_create(tids[i], NULL, sell_ticket, NULL); } sleep(20); // 等待所有线程完成 return 0; }运行这个程序时你可能会看到各种奇怪的现象同一张票被多个售票员卖出、票号不连续、甚至卖出超过20张票。这就是典型的竞态条件问题 - 当多个线程同时访问和修改共享资源(ticket_sum)时由于执行顺序的不确定性导致的数据不一致。我曾在实际项目中遇到过类似问题。当时我们开发一个电商秒杀系统在高并发场景下出现了商品超卖的情况。调试过程让我深刻理解了多线程同步的重要性 - 就像现实中的售票窗口需要排队机制一样程序中的共享资源访问也需要同步机制来保证秩序。2. 互斥锁最简单的同步武器互斥锁(Mutex)是最基础的线程同步工具它的工作原理就像厕所的门锁 - 一个人进去后锁门其他人必须等待。在编程中互斥锁只有两种状态锁定(locked)和解锁(unlocked)。让我们用互斥锁改造之前的售票程序#includepthread.h pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER; void *sell_ticket(void *arg) { for(int i0; i20; i) { pthread_mutex_lock(mutex); // 加锁 if(ticket_sum 0) { sleep(1); printf(%u 卖出第%d张票\n, pthread_self(), 20-ticket_sum1); ticket_sum--; } pthread_mutex_unlock(mutex); // 解锁 } return NULL; }这里有几个关键点需要注意互斥锁需要在全局范围初始化加锁和解锁必须成对出现临界区(加锁和解锁之间的代码)应该尽可能短我在实际使用中发现不当的加锁方式会导致性能问题甚至死锁。比如忘记解锁会导致其他线程永久等待嵌套加锁可能导致死锁过大的临界区会降低并发性能互斥锁适合保护简单的共享资源访问但它有个明显缺点同一时刻只允许一个线程访问资源即使只是读取操作。这在读多写少的场景下会造成不必要的性能损耗。3. 信号量更灵活的同步控制信号量(Semaphore)是Dijkstra提出的一种更通用的同步机制。不同于互斥锁的二元状态信号量是一个计数器可以更灵活地控制资源访问。信号量有两种主要类型二进制信号量(值0或1)功能类似互斥锁计数信号量(值≥0)控制有限资源的并发访问让我们用二进制信号量实现售票同步#includesemaphore.h sem_t sem; sem_init(sem, 0, 1); // 初始值为1 void *sell_ticket(void *arg) { for(int i0; i20; i) { sem_wait(sem); // P操作(减1) if(ticket_sum 0) { sleep(1); printf(%u 卖出第%d张票\n, pthread_self(), 20-ticket_sum1); ticket_sum--; } sem_post(sem); // V操作(加1) } return NULL; }计数信号量更适合控制有限资源的并发访问。比如限制数据库连接池的最大连接数sem_t db_sem; sem_init(db_sem, 0, 10); // 允许10个并发连接 void *query_db(void *arg) { sem_wait(db_sem); // 获取连接 // 执行数据库操作 sem_post(db_sem); // 释放连接 return NULL; }信号量的优势在于它可以跨进程使用(设置pshared参数为1)并且可以初始化为任意正值。但使用起来也比互斥锁更复杂需要特别注意确保每次wait都有对应的post避免死锁情况正确初始化计数值4. 条件变量等待特定条件的发生条件变量(Condition Variable)用于线程间的条件等待和通知机制。它总是与互斥锁配合使用解决了忙等待的效率问题。考虑一个生产者-消费者场景生产者线程生成数据消费者线程处理数据。当没有数据时消费者应该等待而不是不断轮询。pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond PTHREAD_COND_INITIALIZER; int data_ready 0; // 生产者线程 void *producer(void *arg) { while(1) { pthread_mutex_lock(mutex); // 生产数据 data_ready 1; pthread_cond_signal(cond); // 通知消费者 pthread_mutex_unlock(mutex); } } // 消费者线程 void *consumer(void *arg) { while(1) { pthread_mutex_lock(mutex); while(!data_ready) { pthread_cond_wait(cond, mutex); // 自动释放锁并等待 } // 处理数据 data_ready 0; pthread_mutex_unlock(mutex); } }条件变量的使用有几个关键点总是与互斥锁配合使用等待前必须先获取锁使用while循环检查条件(避免虚假唤醒)pthread_cond_wait会原子性地释放锁并进入等待我在开发消息队列时曾大量使用条件变量。它特别适合这种场景线程需要等待某个条件成立才能继续执行而不必忙等待消耗CPU资源。5. 读写锁读多写少的优化方案读写锁(Read-Write Lock)是对互斥锁的优化它区分了读操作和写操作多个读操作可以并发执行写操作需要独占访问读和写操作互斥这种特性非常适合读多写少的场景比如配置管理pthread_rwlock_t rwlock PTHREAD_RWLOCK_INITIALIZER; Config config; // 读线程(多个可并发) void *read_config(void *arg) { pthread_rwlock_rdlock(rwlock); // 读取配置 pthread_rwlock_unlock(rwlock); } // 写线程(独占访问) void *write_config(void *arg) { pthread_rwlock_wrlock(rwlock); // 修改配置 pthread_rwlock_unlock(rwlock); }读写锁的实现通常优先考虑读操作这可能导致写操作饥饿(长时间等待)。某些实现提供了公平策略的读写锁来解决这个问题。在实际项目中我使用读写锁优化过一个缓存系统将读取性能提升了3倍。但需要注意不要长时间持有读锁会影响写操作升级锁时要小心(从读锁升级到写锁可能死锁)考虑使用带超时的版本避免长时间阻塞6. 四种武器的对比与选型经过上面的详细讲解我们来总结一下四种同步机制的特点和适用场景机制特点适用场景性能考虑互斥锁简单、严格互斥简单的共享资源保护临界区要尽可能短信号量计数器、灵活控制并发数资源池、生产者消费者适合跨进程同步条件变量条件等待、避免忙等待事件驱动、任务队列注意虚假唤醒问题读写锁读共享、写独占读多写少的配置、缓存系统注意写操作饥饿问题选择同步机制时我通常考虑以下因素访问模式是纯互斥、读多写少还是条件等待性能需求是否需要最大化并发性能复杂度能否正确实现同步逻辑可维护性代码是否清晰易懂在开发过程中我建议先用最简单的互斥锁实现功能再根据性能测试结果决定是否需要更复杂的同步机制。过早优化往往会导致代码复杂度和bug增加。

相关文章:

C语言多线程同步实战:从竞态到协同的四种武器

1. 多线程售票问题:竞态条件的典型场景 想象一下春运期间的火车站售票窗口,4个售票员同时售卖20张车票。如果缺乏有效的管理机制,很可能出现同一张票被重复售卖,或者票数统计出错的情况。这个场景完美模拟了多线程编程中最经典的…...

OpenClaw人人养虾:健康检查(macOS)

如何从菜单栏应用查看关联频道是否健康。 菜单栏 状态点现在反映 Baileys 健康状态: 绿色:已关联 socket 最近已打开。橙色:正在连接/重试。红色:已登出或探测失败。 次要行显示 "linked auth 12m" 或显示失败原因。…...

解锁论文写作新境界:书匠策AI,你的毕业论文智能导航员!

在学术的浩瀚海洋中,每一位即将毕业的大学生或研究生都像是勇敢的航海家,驾驶着知识的帆船,向着那座名为“毕业论文”的灯塔奋力前行。然而,航程中难免会遇到风浪与迷雾,如何高效、准确地完成一篇高质量的毕业论文&…...

Win11Debloat:三步焕新Windows系统,让老电脑性能提升50%的开源神器

Win11Debloat:三步焕新Windows系统,让老电脑性能提升50%的开源神器 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other chan…...

OpenClaw人人养虾:Windows (WSL2)

OpenClaw 在 Windows 上通过 WSL2(Windows Subsystem for Linux 2,适用于 Linux 的 Windows 子系统)运行。WSL2 提供完整的 Linux 环境,性能接近原生。 系统要求 项目要求Windows 版本Windows 10 (21H2) 或 Windows 11CPU支持虚…...

2026年OpenCLaw知识星球大比拼:谁是技术前沿领跑者?

随着人工智能(AI)技术的迅猛发展,OpenCLaw作为一项重要的编程框架,已经成为了众多开发者和企业的首选工具。然而,面对市场上琳琅满目的OpenCLaw教学资源,如何选择最适合自己的学习平台成为了一个难题。本文…...

如何快速上手AICoverGen:免费制作专业级AI翻唱歌曲的完整指南

如何快速上手AICoverGen:免费制作专业级AI翻唱歌曲的完整指南 【免费下载链接】AICoverGen A WebUI to create song covers with any RVC v2 trained AI voice from YouTube videos or audio files. 项目地址: https://gitcode.com/gh_mirrors/ai/AICoverGen …...

OpenClaw资源监控方案:Qwen3.5-9B运行时性能调优

OpenClaw资源监控方案:Qwen3.5-9B运行时性能调优 1. 为什么需要关注资源监控? 去年冬天,我第一次在本地MacBook Pro上部署Qwen3.5-9B模型时,系统突然卡死的经历让我记忆犹新。当时我正在运行一个简单的文档摘要任务,…...

GetQzonehistory:QQ空间数据备份工具全指南

GetQzonehistory:QQ空间数据备份工具全指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 一、价值定位:数字记忆的守护者 1.1 数据永存的必要性 在数字时代&…...

Python实战:利用imageio与PIL打造高效图片转视频工具

1. 为什么需要图片转视频工具? 在日常工作和生活中,我们经常会遇到需要将多张图片合成为视频的场景。比如制作产品演示视频、创建旅行相册、生成数据可视化动画等。手动使用视频编辑软件处理这些需求不仅效率低下,而且难以实现批量自动化处理…...

3个实战技巧:彻底解锁Cursor Pro功能的高效完整指南

3个实战技巧:彻底解锁Cursor Pro功能的高效完整指南 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your trial…...

AI服务的可观测性与运维

AI服务的可观测性与运维 当 AI 服务从开发环境走向生产,可观测性(Observability)成为运维的基石。传统的监控(CPU、内存、请求量)已不足以应对 AI 系统的复杂性,我们需要深入追踪 每个 AI 交互的细节&#…...

实战应用:在快马平台用jdk1.8的Stream API快速实现订单数据统计与分析

最近在做一个电商后台的数据分析需求时,发现用Java 8的Stream API处理集合数据特别高效。正好在InsCode(快马)平台上实践了一下,分享这个模拟订单统计的实战案例。 订单类设计 首先定义了一个订单类,包含订单ID、金额、客户类型和创建日期四个…...

OpenClaw自动化效率对比:Qwen3.5-9B-AWQ-4bit与GPT-4V多模态任务实测

OpenClaw自动化效率对比:Qwen3.5-9B-AWQ-4bit与GPT-4V多模态任务实测 1. 测试背景与实验设计 去年冬天,我在整理家庭相册时萌生了一个想法:能否用AI自动识别照片内容并生成描述?这促使我开始探索OpenClaw与多模态模型的结合。经…...

中微半导体冲刺港股:年营收11亿 利润2.8亿 周彦套现3.47亿

雷递网 雷建平 4月5日中微半导体( 深圳)股份有限公司(简称:“中微半导体”)日前递交招股书,准备在港交所上市。中微半导体2022年8月在科创板上市,发行6300万股,发行价为30.86元,募资总额19.44亿…...

如何让老照片焕发新生?图像超分技术的4大突破与分辨率增强实践

如何让老照片焕发新生?图像超分技术的4大突破与分辨率增强实践 【免费下载链接】SwinIR SwinIR: Image Restoration Using Swin Transformer (official repository) 项目地址: https://gitcode.com/gh_mirrors/sw/SwinIR 在数字时代,我们常常遇到…...

Postman便携版:Windows免安装API开发工具的新选择

Postman便携版:Windows免安装API开发工具的新选择 【免费下载链接】postman-portable 🚀 Postman portable for Windows 项目地址: https://gitcode.com/gh_mirrors/po/postman-portable 在现代API开发流程中,开发者常常面临工具安装繁…...

手把手教程:Qwen-Image快速部署,小白也能轻松玩转AI绘画

手把手教程:Qwen-Image快速部署,小白也能轻松玩转AI绘画 1. 教程介绍 今天我们要一起探索的是阿里云通义千问团队推出的Qwen-Image图像生成模型。这个模型最大的特点就是能精准理解你的文字描述,生成包含复杂文本的高质量图像。想象一下&am…...

AutoUnipus学习效率工具:提升在线学习体验的智能辅助方案

AutoUnipus学习效率工具:提升在线学习体验的智能辅助方案 【免费下载链接】AutoUnipus U校园脚本,支持全自动答题,百分百正确 2024最新版 项目地址: https://gitcode.com/gh_mirrors/au/AutoUnipus 在数字化学习环境中,学生常面临在线课程任务繁重…...

让业务人员直接“问“数据库:Spring AI Alibaba NL2SQL 实战指南

不用学 SQL,不用找开发排期,用大白话就能查数据——这不是未来,而是现在就能落地的方案。 一个真实的痛点 你是公司的运营负责人,想知道"上个月华东地区复购率最高的三个品类"。 在传统模式下,这个需求的链…...

DS4Windows终极教程:3分钟让PlayStation手柄完美兼容Windows游戏

DS4Windows终极教程:3分钟让PlayStation手柄完美兼容Windows游戏 【免费下载链接】DS4Windows Like those other ds4tools, but sexier 项目地址: https://gitcode.com/gh_mirrors/ds/DS4Windows 还在为PC游戏不支持你的PlayStation手柄而烦恼吗?…...

如何高效一键完整导出QQ空间历史说说:GetQzonehistory专业指南

如何高效一键完整导出QQ空间历史说说:GetQzonehistory专业指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory GetQzonehistory是一款专业的开源工具,专门用于自…...

微信数据解密技术全解析:从原理到合规应用

微信数据解密技术全解析:从原理到合规应用 【免费下载链接】PyWxDump 删库 项目地址: https://gitcode.com/GitHub_Trending/py/PyWxDump 合规使用声明 本文所介绍的技术与工具仅适用于个人合法拥有的数据管理场景。使用者必须确保:1) 仅对本人所…...

C++的std--ranges算法自定义比较器与投影函数在排序中的组合使用

C20引入的std::ranges库为算法操作带来了更简洁、更安全的表达方式,其中自定义比较器与投影函数的组合使用尤其值得关注。这种组合不仅提升了代码的可读性,还能实现复杂的排序逻辑,让开发者能够更灵活地处理数据结构。本文将深入探讨这一特性…...

FanControl:智能风扇控制的全方位解决方案

FanControl:智能风扇控制的全方位解决方案 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/FanControl…...

5种手柄映射方案让手游玩家实现主机级操控体验

5种手柄映射方案让手游玩家实现主机级操控体验 【免费下载链接】escrcpy 📱 Display and control your Android device graphically with scrcpy. 项目地址: https://gitcode.com/GitHub_Trending/es/escrcpy 手机游戏操控优化一直是困扰玩家的核心痛点&…...

OpenClaw本地部署指南:千问3.5-9B接口配置与调试技巧

OpenClaw本地部署指南:千问3.5-9B接口配置与调试技巧 1. 为什么选择OpenClaw千问3.5-9B组合 去年我在尝试自动化处理日常工作报告时,发现市面上的RPA工具要么功能臃肿,要么需要将数据上传到云端处理。直到遇到OpenClaw这个开源框架&#xf…...

第八章:实战项目案例

第八章:实战项目案例 8.1 项目一:Todo 应用(Vue 3 Pinia) 项目初始化 npm create vitelatest todo-app -- --template vue cd todo-app npm install pinia npm install -D vitejs/plugin-vue项目结构 todo-app/ ├── src/ …...

granite-4.0-h-350m效果展示:中英双语问答、代码补全、文本摘要三连击

granite-4.0-h-350m效果展示:中英双语问答、代码补全、文本摘要三连击 今天带大家看看一个轻量级但能力不俗的AI模型——granite-4.0-h-350m。这个模型虽然只有3.5亿参数,但在多个任务上的表现却让人眼前一亮。我用Ollama部署了它的文本生成服务&#x…...

重磅!GPT-6曝光了

就在刚刚,有知情人士爆料:GPT-6正在内测,预计4月16日正式发布。消息源头,是X平台上的科技大V 草莓哥iruletheworldmo。他说,最近OpenAI内部将有大动作,他从中搞到了不少猛料。草莓哥说了一些关键信息&#…...