news 2026/1/18 18:53:25

应用——线程竞争资源模型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
应用——线程竞争资源模型

多线程并发编程笔记:线程竞争资源模型

一、代码示例对比分析

示例1:带线程ID的窗口竞争模型

#include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> #include <time.h> int win = 3; // 可用窗口数 pthread_mutex_t mutex; void *th(void *arg) { int id = *(int *)arg; // 获取线程ID sleep(rand() % 5); // 随机延迟0-4秒 while (1) // 持续尝试直到成功 { pthread_mutex_lock(&mutex); if(win > 0) // 检查是否有可用窗口 { win--; // 占用一个窗口 pthread_mutex_unlock(&mutex); printf("%d:get win\n", id); // 显示获取成功 sleep(rand() % 3 + 1); // 模拟使用窗口1-3秒 pthread_mutex_lock(&mutex); win++; // 释放窗口 pthread_mutex_unlock(&mutex); printf("%d:relese win\n", id); // 显示释放 break; // 退出循环 } else { printf("%d: 没有可用窗口,等待...\n", id); pthread_mutex_unlock(&mutex); sleep(1); // 等待1秒后重试 } } return NULL; } int main(int argc, char **argv) { srand(time(NULL)); // 初始化随机种子 pthread_t tid[10]; // 线程ID数组 int id[10]; // 线程编号数组 // 初始化线程编号 for (int i = 0; i < 10; i++) { id[i] = i + 1; } pthread_mutex_init(&mutex, NULL); // 初始化互斥锁 // 创建10个线程 for (int i = 0; i < 10; i++) { pthread_create(&tid[i], NULL, th, &id[i]); } // 等待所有线程结束 for (int i = 0; i < 10; i++) { pthread_join(tid[i], NULL); } pthread_mutex_destroy(&mutex); // 销毁互斥锁 return 0; }

示例2:匿名线程竞争模型

#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> int win = 3; // 可用窗口数 pthread_mutex_t mutex; void* th(void* arg) { while (1) { pthread_mutex_lock(&mutex); if (win > 0) // 检查是否有可用窗口 { win--; // 占用窗口 pthread_mutex_unlock(&mutex); printf("get win...\n"); // 获取成功 sleep(rand() % 5 + 1); // 使用窗口1-5秒 pthread_mutex_lock(&mutex); win++; // 释放窗口 printf("relese win...\n"); pthread_mutex_unlock(&mutex); break; // 完成任务 } else { pthread_mutex_unlock(&mutex); // 这里没有等待逻辑,会快速重试 } } return NULL; } int main(int argc, char** argv) { int i = 0; srand(time(NULL)); // 初始化随机种子 pthread_t tid[10] = {0}; // 线程ID数组 pthread_mutex_init(&mutex, NULL); // 初始化互斥锁 // 创建10个线程 for (i = 0; i < 10; i++) { pthread_create(&tid[i], NULL, th, NULL); // 不传递参数 } // 等待所有线程结束 for (i = 0; i < 10; i++) { pthread_join(tid[i], NULL); } pthread_mutex_destroy(&mutex); // 销毁互斥锁 return 0; }

示例3:多互斥锁竞争模型(trylock实现)

#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> pthread_mutex_t mutex1; // 窗口1的锁 pthread_mutex_t mutex2; // 窗口2的锁 pthread_mutex_t mutex3; // 窗口3的锁 void* th(void* arg) { int ret = 0; while (1) { // 尝试获取窗口1 ret = pthread_mutex_trylock(&mutex1); if (0 == ret) { printf("get win1...\n"); sleep(rand() % 5 + 1); printf("release win1...\n"); pthread_mutex_unlock(&mutex1); break; } else { // 尝试获取窗口2 ret = pthread_mutex_trylock(&mutex2); if (0 == ret) { printf("get win2...\n"); sleep(rand() % 5 + 1); printf("release win2...\n"); pthread_mutex_unlock(&mutex2); break; } else { // 尝试获取窗口3 ret = pthread_mutex_trylock(&mutex3); if (0 == ret) { printf("get win3...\n"); sleep(rand() % 5 + 1); printf("release win3...\n"); pthread_mutex_unlock(&mutex3); break; } else { // 所有窗口都忙,可以添加等待逻辑 // 当前版本会忙等待 } } } } return NULL; } int main(int argc, char** argv) { int i = 0; srand(time(NULL)); pthread_t tid[10] = {0}; pthread_mutex_init(&mutex1, NULL); pthread_mutex_init(&mutex2, NULL); pthread_mutex_init(&mutex3, NULL); for (i = 0; i < 10; i++) { pthread_create(&tid[i], NULL, th, NULL); } for (i = 0; i < 10; i++) { pthread_join(tid[i], NULL); } pthread_mutex_destroy(&mutex1); pthread_mutex_destroy(&mutex2); pthread_mutex_destroy(&mutex3); return 0; }

二、三种模型对比分析

1.设计思路对比

模型

核心思想

资源表示

竞争方式

模型1

集中式管理

计数器(win)

所有线程竞争一个锁,检查计数器

模型2

简化集中式

计数器(win)

同上,但无线程ID和等待消息

模型3

分布式管理

三个独立锁

每个窗口独立锁,trylock轮询

2.实现复杂度对比

模型

锁数量

代码复杂度

灵活性

模型1

1个互斥锁

中等

窗口数量易扩展

模型2

1个互斥锁

简单

功能最简

模型3

3个互斥锁

较高

每个窗口独立控制

3.性能特点对比

模型锁竞争公平性并发度
模型1高(一个锁)FIFO近似公平
模型2高(一个锁)不确定
模型3低(三个锁)优先抢占

三、关键技术点详解

1.pthread_mutex_trylock 使用

int ret = pthread_mutex_trylock(&mutex); // 返回值: // 0: 成功获取锁 // EBUSY: 锁已被占用 // 其他: 错误

2.锁的初始化与销毁

// 初始化 pthread_mutex_init(&mutex, NULL); // 或静态初始化 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 销毁 pthread_mutex_destroy(&mutex);

3.线程创建与等待

// 创建线程 pthread_create(&tid[i], NULL, thread_func, &arg); // 等待线程结束 pthread_join(tid[i], NULL);

四、问题与改进

1.问题

示例1.2问题
Q1: 为什么线程执行顺序不确定?
  • 操作系统线程调度具有随机性

  • sleep(rand() % 5)引入随机延迟

  • 锁竞争结果不确定

Q2: 如何保证线程安全?
  • 使用互斥锁保护所有共享资源访问

  • 确保加锁和解锁配对出现

  • 避免在临界区内进行耗时操作

Q3: 为什么需要pthread_join
  • 等待线程完成,防止主线程提前退出

  • 回收线程资源

  • 确保所有任务完成

Q4: 如何优化性能?
  • 减少临界区内的操作

  • 使用读写锁(如果适用)

  • 考虑无锁数据结构

示例3的问题
  1. 忙等待问题:所有窗口都忙时,线程会快速轮询,消耗CPU

  2. 饥饿问题:可能某些线程永远抢不到窗口

  3. 优先级固定:总是先尝试窗口1,然后是2、3

2.改进方案:

// 改进版:添加随机等待和公平性 void* th_improved(void* arg) { int ret = 0; int try_count = 0; while (1) { // 随机选择尝试顺序,提高公平性 int order[3] = {0, 1, 2}; shuffle(order, 3); // 随机打乱顺序 for (int i = 0; i < 3; i++) { pthread_mutex_t* mutexes[3] = {&mutex1, &mutex2, &mutex3}; ret = pthread_mutex_trylock(mutexes[order[i]]); if (0 == ret) { printf("get win%d...\n", order[i]+1); sleep(rand() % 5 + 1); printf("release win%d...\n", order[i]+1); pthread_mutex_unlock(mutexes[order[i]]); return NULL; } } // 所有窗口都忙,指数退避等待 try_count++; int wait_time = (1 << try_count); // 指数增长 if (wait_time > 8) wait_time = 8; printf("all windows busy, waiting %d seconds...\n", wait_time); sleep(wait_time); } return NULL; }

五、应用场景建议

1.使用模型1(计数器)的场景:

  • 资源完全同质化

  • 需要精确控制资源总数

  • 扩展性要求高(窗口数量可能变化)

2.使用模型2(简化版)的场景:

  • 快速原型开发

  • 调试和演示

  • 资源竞争不激烈

3.使用模型3(多锁)的场景:

  • 资源有差异(如不同服务窗口)

  • 需要高并发性能

  • 可以接受一定的不公平性

六、最佳实践总结

  1. 根据需求选模型

    • 同质资源 → 计数器模型

    • 异质资源 → 多锁模型

    • 简单场景 → 简化模型

  2. 避免忙等待

    • trylock失败后适当sleep

    • 使用指数退避策略

    • 考虑使用条件变量

  3. 确保资源释放

    • 每个lock都要有对应的unlock

    • 所有退出路径都要释放锁

    • 主线程等待所有子线程

  4. 错误处理

    • 检查pthread函数返回值

    • 添加适当的日志输出

    • 考虑线程安全的错误处理

  5. 性能优化

    • 减少临界区大小

    • 避免在锁内进行IO操作

    • 根据竞争程度调整策略

七、扩展思考

  1. 信号量替代方案:可以使用信号量(semaphore)更简洁地实现资源计数

  2. 条件变量:使用条件变量避免忙等待,节省CPU资源

  3. 线程池:对于频繁创建销毁的场景,考虑使用线程池

这个模型是多线程编程的基础模式,广泛应用于:

  • 数据库连接池

  • 网络服务器连接管理

  • 生产者消费者问题

  • 资源池管理等场景

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/8 17:18:17

如何训练自己的情感语音模型?从EmotiVoice开始

如何训练自己的情感语音模型&#xff1f;从 EmotiVoice 开始 在虚拟主播的直播间里&#xff0c;一句“家人们谁懂啊”可以带着夸张的惊喜脱口而出&#xff1b;而在心理陪伴机器人的轻声细语中&#xff0c;“我在这里陪着你”又需要透出温柔与共情。同样是文字转语音&#xff0c…

作者头像 李华
网站建设 2026/1/11 22:30:26

OpenUSD场景导出终极指南:一键实现USDZ与glTF格式转换

在3D内容创作与分发日益普及的今天&#xff0c;OpenUSD作为通用场景描述框架&#xff0c;其强大的场景组合能力为数字内容管理提供了全新解决方案。然而在实际工作流中&#xff0c;如何高效完成USDZ与glTF两种主流格式的转换&#xff0c;成为众多开发者面临的技术挑战。本文将为…

作者头像 李华
网站建设 2026/1/3 4:34:59

12306抢票终极指南:从零构建自动化购票系统

还在为春运抢票发愁吗&#xff1f;你可能会遇到这样的困境&#xff1a;手动刷新12306网站&#xff0c;验证码识别困难&#xff0c;提交订单时票已售罄。今天&#xff0c;让我们来试试一种全新的解决方案——基于Python的自动化抢票系统。 【免费下载链接】12306 12306智能刷票&…

作者头像 李华
网站建设 2026/1/5 14:55:16

103本入选!中信所发布2025年度国际期刊预警名单

2025年12月7日&#xff0c;中国科学技术信息研究所&#xff08;简称中信所&#xff09;在第二届玉渊潭科研诚信会议发布了《2025年度国际期刊预警名单》&#xff0c;103种期刊入列&#xff0c;较去年增加52种&#xff0c;创2018年以来入列数量新高。据悉&#xff0c;中信所每年…

作者头像 李华
网站建设 2026/1/3 2:38:03

实战分享:如何构建东南亚高并发跑腿配送系统

东南亚跑腿配送市场正以惊人的速度扩张&#xff0c;预计到2025年市场规模将达到280亿美元。作为开发者&#xff0c;进入这一市场不仅需要理解区域特性&#xff0c;更需要构建能够应对复杂环境的技术架构。本文将从技术实践角度&#xff0c;深入探讨如何在东南亚构建一个稳定、可…

作者头像 李华
网站建设 2026/1/16 2:08:47

企业级跨浏览器自动化终极指南:突破兼容性壁垒的完整解决方案

企业级跨浏览器自动化终极指南&#xff1a;突破兼容性壁垒的完整解决方案 【免费下载链接】skyvern 项目地址: https://gitcode.com/GitHub_Trending/sk/skyvern 在数字化转型浪潮中&#xff0c;企业级自动化工具面临着严峻的浏览器兼容性挑战。不同内核的渲染差异、AP…

作者头像 李华