秒杀多线程第十五篇 多线程十大经典案例之一 双线程读写队列数据

2023-11-11

秒杀多线程第十五篇 多线程十大经典案例之一 双线程读写队列数据

《多线程十大经典案例之一双线程读写队列数据》案例描述:

MFC对话框中一个按钮的响应函数实现两个功能:
显示数据同时处理数据,因此开两个线程,一个线程显示数据(开了一个定时器,响应WM_TIMER消息按照一定时间间隔向TeeChart图表添加数据并显示)同时在队列队尾添加数据,另一个线程从该队列队头去数据来处理。

下面就来解决这个案例。先来分析下。

 

《多线程十大经典案例之一双线程读写队列数据》案例分析:

这个案例是一个线程向队列中的队列头部读取数据,一个线程向队列中的队列尾部写入数据。看起来很像读者写者问题(见《秒杀多线程第十一篇读者写者问题》和《秒杀多线程第十四篇读者写者问题继读写锁SRWLock》),但其实不然,如果将队列看成缓冲区,这个案例明显是个生产者消费者问题(见《秒杀多线程第十篇生产者消费者问题》)。因此我们仿照生产者消费者的思路来具体分析下案例中的“等待”情况:

    1.     当队列为空时,读取数据线程必须等待写入数据向队列中写入数据。也就是说当队列为空时,读取数据线程要等待队列中有数据

    2.     当队列满时,写入数据线程必须等待读取数据线程向队列中读取数据。也就是说当队列满时,写入数据线程要等待队列中有空位

访问队列时,需要互斥吗?这将依赖于队列的数据结构实现,如果使用STL中的vector,由于vector会动态增长。因此要做互斥保护。如果使用循环队列,那么读取数据线程拥有读取指针,写入数据线程拥有写入指针,各自将访问队列中不同位置上的数据,因此不用进行互斥保护。

分析完毕后,再来考虑使用什么样的数据结构,同样依照《秒杀多线程第十篇生产者消费者问题》中的做法。使用两个信号量,一个来记录循环队列中空位的个数,一个来记录循环队列中产品的个数(非空位个数)。代码非常容易写出,下面给出完整的源代码。

 

《多线程十大经典案例之一双线程读写队列数据》完整代码:

[cpp]  view plain copy
  1. //秒杀多线程第十六篇 多线程十大经典案例之一 双线程读写队列数据  
  2. //http://blog.csdn.net/MoreWindows/article/details/8646902  
  3. #include <stdio.h>  
  4. #include <process.h>  
  5. #include <windows.h>  
  6. #include <time.h>  
  7. const int QUEUE_LEN = 5;  
  8. int g_arrDataQueue[QUEUE_LEN];  
  9. int g_i, g_j, g_nDataNum;  
  10. //关键段 用于保证互斥的在屏幕上输出  
  11. CRITICAL_SECTION g_cs;  
  12. //信号量 g_hEmpty表示队列中空位 g_hFull表示队列中非空位  
  13. HANDLE     g_hEmpty, g_hFull;  
  14. //设置控制台输出颜色  
  15. BOOL SetConsoleColor(WORD wAttributes)  
  16. {  
  17.     HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);  
  18.     if (hConsole == INVALID_HANDLE_VALUE)  
  19.         return FALSE;     
  20.     return SetConsoleTextAttribute(hConsole, wAttributes);  
  21. }  
  22. //读数据线程函数  
  23. unsigned int __stdcall ReaderThreadFun(PVOID pM)  
  24. {  
  25.     int nData = 0;  
  26.     while (nData < 20)  
  27.     {  
  28.         WaitForSingleObject(g_hFull, INFINITE);  
  29.         nData = g_arrDataQueue[g_i];  
  30.         g_i = (g_i + 1) % QUEUE_LEN;  
  31.         EnterCriticalSection(&g_cs);  
  32.         printf("从队列中读数据%d\n", nData);  
  33.         LeaveCriticalSection(&g_cs);  
  34.         Sleep(rand() % 300);  
  35.         ReleaseSemaphore(g_hEmpty, 1, NULL);  
  36.     }  
  37.     return 0;  
  38. }  
  39. //写数据线程函数  
  40. unsigned int __stdcall WriterThreadFun(PVOID pM)  
  41. {  
  42.     int nData = 0;  
  43.     while (nData < 20)  
  44.     {  
  45.         WaitForSingleObject(g_hEmpty, INFINITE);  
  46.         g_arrDataQueue[g_j] = ++nData;  
  47.         g_j = (g_j + 1) % QUEUE_LEN;  
  48.         EnterCriticalSection(&g_cs);  
  49.         SetConsoleColor(FOREGROUND_GREEN);  
  50.         printf("    将数据%d写入队列\n", nData);  
  51.         SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);  
  52.         LeaveCriticalSection(&g_cs);  
  53.         Sleep(rand() % 300);  
  54.         ReleaseSemaphore(g_hFull, 1, NULL);  
  55.     }  
  56.     return 0;  
  57. }  
  58. int main()  
  59. {  
  60.     printf("     秒杀多线程第十六篇 多线程十大经典案例 双线程读写队列数据\n");  
  61.     printf(" - by MoreWindows( http://blog.csdn.net/MoreWindows/article/details/8646902 ) -\n\n");  
  62.       
  63.     InitializeCriticalSection(&g_cs);  
  64.     g_hEmpty = CreateSemaphore(NULL, QUEUE_LEN, QUEUE_LEN, NULL);  
  65.     g_hFull = CreateSemaphore(NULL, 0, QUEUE_LEN, NULL);  
  66.       
  67.     srand(time(NULL));  
  68.     g_i = g_j = 0;  
  69.     HANDLE hThread[2];  
  70.     hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ReaderThreadFun, NULL, 0, NULL);  
  71.     hThread[1] = (HANDLE)_beginthreadex(NULL, 0, WriterThreadFun, NULL, 0, NULL);  
  72.       
  73.     WaitForMultipleObjects(2, hThread, TRUE, INFINITE);  
  74.       
  75.     for (int i = 0; i < 2; i++)  
  76.         CloseHandle(hThread[i]);  
  77.     CloseHandle(g_hEmpty);  
  78.     CloseHandle(g_hFull);  
  79.     DeleteCriticalSection(&g_cs);  
  80.     return 0;  
  81. }  

 

《多线程十大经典案例之一双线程读写队列数据》运行结果:

程序运行结果如下:


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

秒杀多线程第十五篇 多线程十大经典案例之一 双线程读写队列数据 的相关文章

  • openGL之API学习(一零四)原子计数 Atomic Counters atomic_uint

    原子计数器 Atomic counters 是OpenGL4 2的新功能 能够用于渲染管线的各个阶段 完整的文档规范说明在GL ARB shader atomic counters 原子计数器是一块缓冲区 缓冲区对象 存放了一个或多个整型
  • 重磅直播丨迈向移动数字金融 —— 神州信息并购云核网络线上发布会

    关注神州信息官微 点击底部菜单栏及时关注
  • Vue3的常见30道核心面试题,会vue3的你,是不是的掌握了

    1 什么是Vue3 Vue3有哪些新增特性 答 Vue3是Vue js框架的最新版本 它增加了很多新特性 包括Composition API Teleport Suspense 和Fragment等 2 Vue3 Composition A
  • 第三节:数据类型——Object对象

    Object对象 由属性构成的无序集合 1 对象与原始类型的区别 对象有属性 对象对应的值可以是原始数据类型也可以是对象 对象的属性和对应的值这种表示方式称之为键值对 属性名又称之为键名 值称之为键值 键值可以是原始数据类型也可以是对象 也
  • 华为机试:统计大写字母个数

    一 题目 描述 找出给定字符串中大写字符 即 A Z 的个数 输入描述 本题含有多组样例输入 对于每组样例 输入一行 代表待统计的字符串 输出描述 对于每组样例 输出一个整数 代表字符串中大写字母的个数 二 输入输出示例 三 代码 incl
  • CPU与GPU计算耗时对比

    下面我们测试了分别使用CPU和GPU执行矩阵乘法得到的耗时差异 运行结果如下 注意 上面的运行揭示了下面几点 cpu c的第一次计算耗时明显超过后面的3次 gpu c的第一次计算耗时明显大大超过后面3次 GPU运行耗时差不多是CPU的1 1
  • shell-test判断

    一 条件判断参数详解 对于test和 中括号 判断语句来说 判断结果为真 则退出值为0 即echo 为0 即返回为true 其他为false 1 关于文件名 文件类型 的判断 e 该 文件名 是否存在 文件和目录都会返回为真 f 该 文件名

随机推荐

  • 基于docker安装mongo

    1 背景 基于业务的需求 部分数据量较大 基本一天的数据量都在1亿左右 关系型数据库已经满足不了了要求 所以更换为非关系型数据库 当然非关系型数据库的种类有很多 我们选择的是mongo 要想了解熟悉mongo 不能只做书面上的功夫 必须较强
  • 微信支付JSAPI支付

    公司业务需求 在公众号中加入微信支付和支付宝支付 效果图如下 菜单的设计直接在公众号中设置就好啦 两个子菜单都是跳转网页形式直接把你服务器上的url复制上就好 一些其他的很重要的配置 微信支付中开发配置 支付测试url 这里是报错 开始以为
  • 记一次centos7 下根目录扩容操作(步骤详细!!!)

    文章目录 需求描述 具体步骤 查看本机磁盘环境 添加磁盘分区 开始扩容 同步到文件系统 参考内容 需求描述 由于测试环境需要 虚拟机根目录需要扩容至120G 具体步骤 查看本机磁盘环境 root localhost df h 文件系统 容量
  • linux中copy_to_user()和copy_from_user()函数

    由于内核空间与用户空间的内存不能直接互访 因此借助函数 copy from user 完成用户空间到内核空间的复制 函数copy to user 完成内核空间到用户空间的复制 copy from user 和 copy to user 的原
  • 从第一人称的角度去带你了解Shell脚本的编写过程及思路

    前言 最近有朋友拿了两个文本给我 里面全都是IP地址 第一个IP地址是已安装相关服务的主机地址 第二个地址则是某一区域的所有主机IP地址 其中第一个文本有部分内容与第二个文本的内容重复 说明是已经安装了的 而第一个文本除了包含第二个文本的部
  • 单节锂电池充放电及外部供电自动切换的电路--原理介绍

    目录 单节锂电池充放电及外部供电自动切换的电路 原理介绍 1 电源输入与输出 2 虚线左边的电路是充电电路 3 虚线右侧的电路是自动切换电路 4 元器件的选择 5 PCB设计建议 单节锂电池充放电及外部供电自动切换的电路 原理介绍 介绍一种
  • 利用matlab建立一个压缩机的热力学数学模型,给出具体的代码

    我不太懂你在说什么 但是我可以提供一些参考资料 可以帮助你建立压缩机的热力学数学模型 1 MATLAB编程指南 https www mathworks com help matlab programming guide html 2 MAT
  • WSL2 在 Windows10下的 网卡 配置问题

    网络上的大部分解决方案是 在Hyper V 的WSL的虚拟交换机中的连接类型改成外部网络 然后在用户目录 USERPROFILE 下面创建一个配置文件 wslconfig wsl2 networkingMode bridged 桥接模式 v
  • CTFHub-web(cookie注入)

    文章目录 一 解题步骤 二 关于sql中 id 多少 的说明 一 解题步骤 1 题目为cookie注入 我们首先先看一下cookie里的值有没有什么可以帮助我们思考的东西 id 1 很明显存在sql注入 2 我们抓包来一步步的进行注入会更方
  • .Net Core跨域处理

    查看官方文档 https docs microsoft com zh cn aspnet core security cors view aspnetcore 2 2 分两部分处理跨域 ConfigureServices里添加 servic
  • 【华为OD机试】模拟消息队列【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 让我们来模拟一个消息队列的运作 有一个发布者和若干消费者 发布者会在给定的时刻向消息队列发送消息若此时消息队列有消费者订阅 这个消息会被发送到订阅的消费者中优先级最高
  • awk的数组学习心得

    http bbs chinaunix net thread 2312439 1 2 html 在文本处理的工作中 awk的数组是必不可少的工具 在这里 同样以总结经验和教训的方式和大家分享下我的一些学习心得 如有错误的地方 请大家指正和补充
  • 医学图像语义分割最佳方法的全面比较:UNet和UNet++

    点击上方 AI公园 关注公众号 选择加 星标 或 置顶 作者 Sergey Kolchenko 编译 ronghuaiyang 导读 在不同的任务上对比了UNet和UNet 以及使用不同的预训练编码器的效果 介绍 语义分割是计算机视觉的一个
  • 超好用的数学公式识别软件mathpix!

    在写科研论文或者其他论文 亦或者将word里的公式搬到latex里进行排版 数学公式总是一项非常艰巨的任务 在电脑上输入的速度远远没有手写来得快 既然如此 有没有办法直接识别手写的公式呢 有 就是这个软件 mathpix 怎么使用呢 下载安
  • Linux-RPM软件包管理/dnf管理软件/源码安装教程/使用systemd管理服务

    文章目录 管理软件包 RPM软件包 Linux软件包管理概述 RPM软件包管理 RPM软件包管理的优缺点 使用RPM命令管理软件 安装 查询 升级 卸载 RPM命令常用参数 RPM命令 安装 RPM命令 卸载 RPM命令 升级 RPM 查询
  • jdbc原理与步骤

    jdbc原理 1 加载JDBC驱动 并将其注册到DriverManager 2 建立数据库连接 获取connection对象 3 建立Statement对象或PreparedStatement对象 4 执行SQL语句 5 访问结果集Resu
  • 送本书《Python 之旅》

    在线阅读 下载 在线阅读 https www bookstack cn books explore python 下载 关注公众号马上码回复 pythonzl Python 是一门面向对象 解释型的高级程序设计语言 它的语法非常简洁 优雅
  • 分析游戏《明日方舟》的成功要素

    明日方舟 这个出身并不显赫 玩法也绝非时下主流的游戏一经上线 就在一个月内连续霸榜 在正式上线一个月的时候 顺理成章地登顶App Store畅销榜榜首 简单介绍游戏信息与核心玩法 游戏名称 明日方舟 英文名称 Arknights 制作厂商
  • element-ui el-tree树形控件 默认箭头更改

    这是基础性 那么怎么修改呢 很简单只需要在css中修改 注意 vue中修改需要添加 deep el icon arrow right color 49c0ff el table el table expand icon el icon ar
  • 秒杀多线程第十五篇 多线程十大经典案例之一 双线程读写队列数据

    秒杀多线程第十五篇 多线程十大经典案例之一 双线程读写队列数据 多线程十大经典案例之一双线程读写队列数据 案例描述 MFC对话框中一个按钮的响应函数实现两个功能 显示数据同时处理数据 因此开两个线程 一个线程显示数据 开了一个定时器 响应W