系列综述:
💞目的:本系列是个人整理为了秋招面试
的,整理期间苛求每个知识点,平衡理解简易度与深入程度。
🥰来源:材料主要源于多处理器编程的艺术
进行的,每个知识点的修正和深入主要参考各平台大佬的文章,其中也可能含有少量的个人实验自证。
🤭结语:如果有帮到你的地方,就点个赞和关注一下呗,谢谢🎈🎄🌷!!!
🌈【C++】秋招&实习面经汇总篇
文章目录
- 绪论
- 并发编程
- 阿姆达法则
- 互斥
- 二级标签
- 二级标签
- 参考博客
😊点此到文末惊喜↩︎
绪论
并发编程
- 多核体系发展的原因
- 单核提升速度降低
- 多核能耗效率高
- 共享存储多处理器(Shared Memory Multiprocessor SMP)
- 多个处理器,共享同一个内存。
- 每个线程对应一段顺序程序,线程之间通过对共享内存中的数据对象进行操作实现通信。
- 线程是异步的,在任何时间都可能延迟一段不可预测的时间
- 多线程并发处理可能导致对于共享内存区域的乱序存储,从而出现错误。
- 解决方式:多线程并发处理的共享内存区域需要保证
互斥访问
,互斥可以保证代码执行的原子性,但是可能降低并发性能 - 核心问题:保证正确性的同时,尽可能的提高并发程度
阿姆达法则
- 定义:假定单个处理器完成作业的时间是1,作业中可并行处理的部分是 p。那么不能并行处理的部分是 1-p。使用 n个处理器完成作业的时间就是 1 − p + p n 1-p + \frac {p}{n} 1−p+np,speedup = 1 1 − p + p n \frac{1}{1-p + \frac {p}{n}} 1−p+np1
- 由阿姆达法则可知,加速比的关键是
减少程序中不可并行处理
的部分
互斥
- 临界区:访问临界资源的那部分代码,临界代码同一时刻只能有一个线程在执行。
- 如果程序的所有代码都互斥,则将无法进行多核的并发。所以应该尽可能降低并发粒度,提高加速比(并发度)。
- 并发性/非确定性
- 安全性:坏的事情永远不会发生,如互斥
- 活性:好的事情一定会发生,如无死锁
- 事件
- 定义:线程执行完成某个动作的时间点
- 本质:线程从一个状态到另一状态的迁移
- 特点:不会有同时发生的事件
- 线程:每个线程的执行是一个事件序列, 在时间上是线性的全序关系。
- 并发:多个线程的事件在时间上的重叠,这些事件不一定相互独立,可能存在共享变量,导致不同线程的事件间存在依赖关系,即线程间无法并发。
- 区间:由两个事件作为起点和终点进行描述的。事件是瞬时性的,区间是持续性的。
- 两个区间的关系
- 相交
- 不相交:区间A的终点在区间B的起点之前,记为 A → B A \rightarrow B A→B,称为A先于B。
- 包含
- 锁:通过共享内存变量来标识,并发的线程是否获得对应临界区的执行权限,从而实现临界区访问的互斥。
- 加锁:线程调用lock方法并返回
- 解锁:线程执行unlock方法并返回
- 细粒度锁往往比粗粒度锁更高效,特别是只针对临界代码的加锁。
- 锁的性质
- 互斥:不同线程的临界区不交叠,即不同线程对临界区的执行是先于关系(严格的偏序线性)
- 无死锁:锁一定会被某个申请的线程获取。个体可能无进展,但系统一定有进展。
- 无饥饿:试图获取一个锁的线程一定会成功获取到锁。所有个体都有进展。
二级标签
二级标签
🚩点此跳转到首行↩︎
参考博客
- 待定引用
- 待定引用
- 待定引用
- 待定引用
- 待定引用
- 待定引用
- 待定引用
- 待定引用