秒杀多线程第四篇 一个经典的多线程同步问题

2023-11-16

上一篇《秒杀多线程第三篇原子操作 Interlocked系列函数》中介绍了原子操作在多进程中的作用,现在来个复杂点的。这个问题涉及到线程的同步和互斥,是一道非常有代表性的多线程同步问题,如果能将这个问题搞清楚,那么对多线程同步也就打下了良好的基础。

程序描述:

主线程启动10个子线程并将表示子线程序号的变量地址作为参数传递给子线程。子线程接收参数 -> sleep(50) -> 全局变量++ -> sleep(0) -> 输出参数和全局变量。

要求:

1.子线程输出的线程序号不能重复。

2.全局变量的输出必须递增。

下面画了个简单的示意图:

分析下这个问题的考察点,主要考察点有二个:

1.主线程创建子线程并传入一个指向变量地址的指针作参数,由于线程启动须要花费一定的时间,所以在子线程根据这个指针访问并保存数据前,主线程应等待子线程保存完毕后才能改动该参数并启动下一个线程。这涉及到主线程与子线程之间的同步

2.子线程之间会互斥的改动和输出全局变量。要求全局变量的输出必须递增。这涉及到各子线程间的互斥

下面列出这个程序的基本框架,可以在此代码基础上进行修改和验证。

//经典线程同步互斥问题
#include <stdio.h>
#include <process.h>
#include <windows.h>

long g_nNum; //全局资源
unsigned int __stdcall Fun(void *pPM); //线程函数
const int THREAD_NUM = 10; //子线程个数

int main()
{
	g_nNum = 0;
	HANDLE  handle[THREAD_NUM];
	
	int i = 0;
	while (i < THREAD_NUM) 
	{
		handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);
		i++;//等子线程接收到参数时主线程可能改变了这个i的值
	}
	//保证子线程已全部运行结束
	WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);  
	return 0;
}

unsigned int __stdcall Fun(void *pPM)
{
//由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来
	int nThreadNum = *(int *)pPM; //子线程获取参数
	Sleep(50);//some work should to do
	g_nNum++;  //处理全局资源
	Sleep(0);//some work should to do
	printf("线程编号为%d  全局资源值为%d\n", nThreadNum, g_nNum);
	return 0;
}

运行结果可以参考下列图示,强烈建议读者亲自试一试。

1

2

3

可以看出,运行结果完全是混乱和不可预知的。本系列将会运用Windows平台下各种手段包括关键段,事件,互斥量,信号量等等来解决这个问题并作一份全面的总结,敬请关注。

秒杀多线程第五篇 经典线程同步 关键段CS》已经发布,欢迎参阅。

秒杀多线程第六篇 经典线程同步 事件Event》已经发布,欢迎参阅。

秒杀多线程第七篇 经典线程同步 互斥量Mutex已经发布,欢迎参阅。

秒杀多线程第八篇 经典线程同步 信号量Semaphore已经发布,欢迎参阅。

转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/7442333

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

秒杀多线程第四篇 一个经典的多线程同步问题 的相关文章

  • Java课程设计之学习成绩管理系统

    package System import java awt import java awt event import java io import javax swing import javax swing table Abstract
  • 终端连接控制(stty的编写)

    终端连接控制 stty的编写 一 背景 文件与目录在之前已经学习过了 文件中包含着数据 这些数据可以被读出 写入 也可以用以操作 但文件不仅仅是计算机唯一的数据来源 计算机的数据还可以来自于许多的外部设备 比如扫描仪 照相机 鼠标等输入设备
  • linux 如何创建卷组

    1 创建一个物理卷 Pvcreate dev sd1 dev sd2 dev sd3 dev sd4 2 用刚才创建的物理卷创建一个卷组 Vgcreate 卷组名 dev sd1 dev sd2 dev sd3 dev sd4 3 创建逻辑
  • 计算机领域中随处可见的抽象

    想要管理多种具体的东西 那么需要遵守每种东西的规范 如果想要提供一种通用模式来对这些具体的东西统一管理 需要使用一种古老的技术 抽象 抽象是将多种具体的东西 管理时需要遵守的规范 的共同点抽取出来 放入到更高一层的抽象层 在抽象层不定义或少
  • unix环境高级编程——文件IO

    本期主题 unix环境高级编程 文件IO 文件IO 0 引言 1 文件描述符 2 IO编程中常用的API接口 1 open函数 2 close函数 3 read函数 4 write函数 5 lseek函数 3 函数sync fsync和fd
  • 设备管理过程

    复杂度2 5 机密度2 5 最后更新2021 04 19 AIX中对设备会有如下五个操作 define aix下能看到设备的定义 但驱动程序并没有加载或初始化 该设备不可用 lsdev看到设备时defined 很多逻辑设备 vg lv等 只
  • JSON.stringify()

    JSON stringify 将一个JavaScript值 对象或者数组 转换为一个 JSON字符串 如果指定了replacer是一个函数 则可以选择性的替换值 或者如果指定了replacer是一个数组 可选择性的仅包含数组指定的属性 语法
  • office2013 excel 打开时提示excel词典xllex.dll文件丢失或损坏

    今天打开Excel时 发现报错 xllex dll文件丢失或损坏 我用的是office2013 网上找了好多都是2007的dll文件 导入不了 于是乎重装office 问题解决 但还是把xllex dll烤出来做个备份吧 参考下面步骤即可
  • Linux,Network manager 导致节点异常重启

    推断是Network manager 导致的 原因待查今天在VmWare的虚拟机上装了个测试RAC 又遇到了一个摸不到头绪的问题CRS装好后 一旦登陆图形界面 节点就重启 事情就有这么巧不登陆图形界面 观察了1个小时没问题 一旦登陆后 立刻
  • Linux学习--CentOS7.5

    CentOS7命令大全 Linux系统简介 Unix Linux发展史 Linux目录结构 树形结构 查看 切换以及创建目录 文本内容操作 grep工具 关机和重启 Linux命令 基本用法 ls list 使用通配符 mkdir 别名 g
  • 使用inet_ntop转换IPv6地址时在macOS和linux上的行为不一样

    下面这段python代码在macOS和linux时运行的结果是不同的 import socket ip socket inet pton socket AF INET6 1 2 3 0 5 6 7 8 print socket inet n
  • Linux 内核中的 Device Mapper 机制

    Linux 内核中的 Device Mapper 机制 尹 洋 在读博士生 尹洋 中科院计算所国家高性能计算机工程技术研究中心的在读博士生 主要从事服务部署和存储资源管理以及Linux块设备一级的开发和研究工作 简介 本文结合具体代码对 L
  • 内存管理——分页分段

    一 分页存储管理 1 页面与页框 1 页面 将一个进程的逻辑地址空间分成若干个大小相等的片 称为页面或页 并为各页加以编号 2 页框 相应于页面 把内存空间分成和页面相同大小的若干个存储块 称为 物理 块或页框 frame 3 页内碎片 在
  • OS——文件管理系统磁盘的结构之搞清盘面和柱面

    如上图 每个柱面有三个盘面 即就是3个磁道 柱面可以抽象的理解成是一个套一个的立体的同心圆柱体 例 2019年408真题 磁盘有300个柱面 每个柱面有10个磁道 每个磁道有200个扇区 扇区大小为512B 则磁盘容量 分析 每个柱面有10
  • linux 使用systemctl 启动服务报错: Error: No space left on device

    By default Linux only allocates 8192 watches for inotify which is ridiculously low And when it runs out the error is als
  • java IO、NIO、AIO详解

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 IO流 同步 阻塞 二 NIO 同步 非阻塞 三 NIO2 异步 非阻塞 正文 回到顶部 概述 在我们学习Java的IO流之前 我们都要了解几个关键词 同步与异步 sy
  • C#实现FTP文件夹下载功能【转载】

    网上有很多FTP单个文件下载的方法 前段时间需要用到一个FTP文件夹下载的功能 于是找了下网上的相关资料结合MSDN实现了一段FTP文件夹下载的代码 实现的思路主要是通过遍历获得文件夹下的所有文件 当然 文件夹下可能仍然存在文件夹 这样就需
  • gdb attach 进程调试

    gdb调试正在运行的进程 GDB可以对正在执行的程序进行调度 它允许开发人员中断程序 并查看其状态 之后还能让这个程序正常地继续执行 gdb attach xxxxx xxxxx为利用ps命令获得的子进程process
  • Linux(12):磁盘配额(Quota)与进阶文件系统管理

    磁盘配额 Quota 的应用与实作 Quota 的一般用途 针对 www server 例如 每个人的网页空间的容量限制 针对 mail server 例如 每个人的邮件空间限制 针对 file server 例如 每个人最大的可用网络硬盘
  • 【操作系统xv6】学习记录4-一级页表与二级页表

    占位

随机推荐