线程间共享资源冲突的场景

多个线程之间共享虚拟空间地址,也就是很多资源都是共享的(临界资源),这样最大的优点就在于通信方便,同时也存在弊端,那就是缺乏访问控制。两个线程如果访问并修改同一个全局变量,这就容易引发逻辑错误,甚至有可能造成线程崩溃。

至于线程崩溃具体是怎样的,下面从两方面介绍,一方面是站在底层的角度了解,然后另一方面是通过代码测试的结果更直观的看到线程逻辑错误的影响。


目录

一、线程因临界资源产生冲突的情景(感性认识)

1、了解 tickets-- 的过程(站在内存的角度)

2、临界资源冲突情景

二、线程资源冲突代码重现(理性认识)

1、测试代码及测试结果

2、测试结果分析

三、解决线程“乱入”:为临界区加锁


一、线程因临界资源产生冲突的情景(感性认识)

现在有一个抢票软件,一共有2个线程在抢票,抢到了则总票数tickets自减,一开始tickets = 1000,在那之前我们需要了解 tickets-- 的过程。

1、了解 tickets-- 的过程(站在内存的角度)

tickets -- 并非像我们认识的那样,直接一步到位。站在OS的角度,实际上分成了三步,转换成汇编语言以后也是分成了至少三步来实现。

第一步,CPU会先把 tickets 的值加载CPU的寄存器上;

第二步,CPU判断 tickets>0 或者 tickets--;

第三步,将修改以后的 tickets 值或者判断结果返回给内存。

2、临界资源冲突情景

现在开始抢票,假设CPU是按照编号顺序调度线程,注意是假设,真实情况不一定。当第 0 号线程,刚好进行完第一步以后,才刚把数据加载到CPU的寄存器上,还没来得及进行第二步,时间片就到了,于是第 0 号线程就拿着上下文数据排到运行队列的队尾(这里的上下文数据指的是tickets的值1000)

下面第1号线程接上,1号线程没有受到什么阻碍,一直在抢票,顺利的把tickets减少到 990 张,第1号线程保存了上下文数据tickets的值,排到队尾。

现在又轮到第0号线程了,CPU先把上下文数据加载到寄存器里,然后再开始进行第二步、第三步,此时上下文的 tickets = 1000,等抢到5张票以后时间片到了,内存中的票数被改成了 995,第0号线程又带着上下文数据 tickets = 995 排到队尾

到这里我们就会发现问题了,第0号线程第二次被调度的时候,把内存中tickets = 990 改成了 tickets = 995,那第1号线程岂不是白干活了??这个时候两个线程就发生了冲突

二、线程资源冲突代码重现(理性认识)

说了一堆理论的,下面我们使用代码来还原上面的过程

1、测试代码及测试结果

电影院售票100张,我们开设5个线程同时开始抢票,抢到了就打印还剩多少张票,这里我们要重点关注的是打印的结果

=====================子线程=====================

=====================主线程=====================

 =====================Makefile文件=====================

 测试结果如下,我们会发现票数出现了负数!!

2、测试结果分析

关于上面的现象,我们可以这么理解,当线程3进来的时候,此时ticket = 1,正准备自减的时候,相当于正好加载到CPU的寄存器上时,线程3的时间片到了,此时要轮到线程4被CPU调度了

 线程4的tickets = 0,正好接上线程3开始自减,自减以后tickets就变成了-1

 等到下一次线程4再次遇到,前面一个线程刚进入 if 语句,时间片就到了,此时线程4再次“乱入”,此时就会把线程4 的tickets打印出来 ,此时就出现了 tickets = -1的情况。

三、解决线程“乱入”:为临界区加锁

解决方案放在下面这篇博客中,含代码和测试结果​​​​​​​

Linux环境下 解决线程共享资源冲突 —— 互斥锁(代码实现及底层原理)_abs(ln(1+NaN))的博客-CSDN博客为了保护这些共享资源在被使用的时候,不会受到其他线程的影响,此时要用的就是互斥锁https://blog.csdn.net/challenglistic/article/details/124755816?spm=1001.2014.3001.5501

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值