深入理解并发问题的产生原因和解决方案

并发问题产生在哪些地方?

​ 在探讨并发原理之前,我们要先明白并发问题的产生原因和产生的地方。如果这些我们不清楚的话,怎么能解决好并发问题呢。首先,我们先观察下面两张图:

在这里插入图片描述

问题1: 上图中 图1和图2中的代码执行逻辑,哪个坑会有问题?
非常明显,图2中的多个CPU同时执行一段代码的时候,是非常容易有问题。当两个CPU交叉去执行同一段代码的时候,非常容易出现问题,

通过上图,我们可以总结出来,并发问题产生的根本原因,就是 CPU穿插执行程序
也就是说:并发问题就是 多个CPU同时操作同一个可读可写的数据

如何解决并发问题?

从上面我们得出的结论,就是多个CPU同时操作同一个可读可写的数据。我们想想,如果一个CPU读写完成,另外一个CPU再进行读写操作。这些并发问题就能完美解决。那么我们思考一下,CPU读写完成,是不是就是一个原子操作。一段操作,要么全部执行,要么全部不执行。

在这里插入图片描述
我们看下上图,CPU要从内存中获取数据,必须通过控制总线,获取数据在内存中的地址。如果,我们给控制总线进行加锁,只能同一时间只有一个CPU占用控制总线,这样就能保证CPU的原子操作了。
上面对控制总线加锁的方案,确实能够解决并发问题,但是又引入另外一个问题,性能问题: 控制总线是整个系统的资源,同一时间只能有一个CPU使用该资源,多核CPU就变得无意义了。
控制总线加锁,导致系统性能严重下降的根本原因: 对控制资源加锁,锁太重了,导致系统资源严重下降。
知道原因之后,那么可以进行降低锁粒度,在CPU内部,加上一层缓存,对缓存行中的数据进行加锁,不影响控制总线的使用。如下图:
在这里插入图片描述

并发产生的地方

在这里插入图片描述
上图是从语言层到CPU层,核心流程图。我们从上图来思考一下,产生并发问题的地方都在哪些地方?

第1处: CPU层次

CPU执行指令片段,如果不进行指令片段的原子操作,那么CPU执行的结果是无法保证的。因此CPU执行代码指令会产生并发问题的。

第2处: OS层次

当不同进行进程进行系统调用的时候,OS需要调度各种资源,系统调用肯定会存在对共同资源的竞争。OS系统调用过程中,也会产生并发问题。

第3处: 进程层次:

在linux中,进程的资源是相互独立,互补影响的。不会存在竞争问题。

第4处: 线程层次

线程是轻量级的进程,线程在进程中资源共享。如果有公共资源,线程之间进行竞争,会发生并发问题的。

综上所述: 并发问题只会存在 CPU层次,OS层次,和我们应用的线程层次。现在CPU和OS已经解决了自己并发的问题: CPU提供了原子指令,OS 中有pthread等函数。而我们开发者只需要处理好应用层次的线程间的并发问题即可。

线程并发问题处理方案

在这里插入图片描述

核心原理

在代码段中设置一个标志位,线程竞争标志位,当获取成功之后,去执行相应的代码段。当获取不成功之后,需要进入等待队列。这个时候,进入等待队列,也需要进行竞争(多个线程没有获取成功),所有,需要对队列的tail指针进行加锁,加锁成功,进入阻塞队列,加锁失败,进行自旋,一直能够加锁成功,进入队列。之前加锁成功,执行完代码之后,会唤醒阻塞队列中的线程,让阻塞队列中的线程重新进行标志位加锁,循环往复,直到执行完代码,线程销毁。

以上就是本次分享的所有内容,如有不足,请多多指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大伟攀高峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值