news 2026/4/28 16:51:26

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

作者头像

张小明

前端开发工程师

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/4/28 10:22:22

sherpa-onnx嵌入式语音识别实战:跨平台部署与性能优化指南

sherpa-onnx嵌入式语音识别实战&#xff1a;跨平台部署与性能优化指南 【免费下载链接】sherpa-onnx k2-fsa/sherpa-onnx: Sherpa-ONNX 项目与 ONNX 格式模型的处理有关&#xff0c;可能涉及将语音识别或者其他领域的模型转换为 ONNX 格式&#xff0c;并进行优化和部署。 项目…

作者头像 李华
网站建设 2026/4/28 0:30:38

FanControl完整教程:Windows风扇智能控制终极方案

还在为电脑风扇噪音和散热效率发愁吗&#xff1f;FanControl这款免费的Windows风扇控制软件能够完美解决您的烦恼。通过智能温度监控和可视化曲线配置&#xff0c;即使是电脑新手也能轻松实现专业级的风扇管理效果。&#x1f31f; 【免费下载链接】FanControl.Releases This is…

作者头像 李华
网站建设 2026/4/25 18:03:10

Sist2终极指南:快速构建企业级文件搜索系统的完整解决方案

Sist2终极指南&#xff1a;快速构建企业级文件搜索系统的完整解决方案 【免费下载链接】sist2 Lightning-fast file system indexer and search tool 项目地址: https://gitcode.com/gh_mirrors/si/sist2 在当今信息爆炸的时代&#xff0c;如何从海量文件中快速找到所需…

作者头像 李华
网站建设 2026/4/27 19:29:41

如何在10分钟内搭建Next.js企业级认证系统

如何在10分钟内搭建Next.js企业级认证系统 【免费下载链接】next-shadcn-dashboard-starter Admin Dashboard Starter with Nextjs14 and shadcn ui 项目地址: https://gitcode.com/gh_mirrors/ne/next-shadcn-dashboard-starter 还在为认证系统开发而头疼吗&#xff1f…

作者头像 李华
网站建设 2026/4/25 14:34:52

基于长短期记忆网络的股票价格预测多维数据需求分析

功能说明 本代码实现了利用长短期记忆网络&#xff08;LSTM&#xff09;进行股票价格预测的量化交易策略&#xff0c;通过整合多维度市场数据构建特征工程&#xff0c;训练深度学习模型对未来股价走势进行分类或回归预测。该方案适用于中低频量化交易场景&#xff0c;可作为趋势…

作者头像 李华
网站建设 2026/4/25 2:38:05

企业客户案例:某公司使用EmotiVoice降本增效实录

企业客户案例&#xff1a;某公司使用EmotiVoice降本增效实录 在内容生产节奏日益加快的今天&#xff0c;一家教育科技公司正面临一个典型难题&#xff1a;如何在不增加人力成本的前提下&#xff0c;为数百小时的在线课程快速生成风格统一、富有感染力的配音&#xff1f;传统的解…

作者头像 李华