并发
并发的概念
串行导致效率低
并发的原理 多道技术
1.空间复用 将内存划分为不同的区域,互相隔离,存入不同的程序数据
2.时间服用 切换+保存状态
切换: 遇到IO操作,或者某个人物执行时间超过阈值
并发的实现方法
多进程
多线程
协程
进程
只一个正在运行的程序
程序的三种状态
阻塞 就绪 运行
重要概念
阻塞 非阻塞 程序的状态
并行 并发 串行 处理任务的方式
同步 方发起一个任务之后,必须等待任务执行结束,才能继续执行其他任务 != 阻塞
异步 发起一个任务之后,无需等待任务执行技术 ,可以执行其他任务 != 非阻塞
进程的使用
实例化 Process累 最制定 target 处理人物的方式
继承自Process类 覆盖run方法 ,创建对象 调动start函数
必须放入__nam__ == __main__中,因为windows中开启子进程 子进程会导入主进程的代码再次执行
守护进程
特点:会随着守护进程的结束而结束
子进程只能守护主进程
僵尸进程 孤儿进程
僵尸进程是有害的 大量僵尸进程将导致无法开启新的进程 可以杀掉父进程
进程安全问题 == 并发/并行 带来的数据安全问题
解决方案:把并发的操作变成串行
1.join 将使得所有代码全部串行 效率低
2.加锁 仅将部分代码串行 加锁的粒度越小效率越高
IPC
进程间通讯
1.共享文件 交互不频繁 数据量大
2.共享内存 交互频繁 数据量较小
1.Manager 没有解决安全问题
2.queue 解决了安全问题 先进先出
3.管道 单向通讯 基于文件 编程复杂
4.socket 更适用于基于网络的通讯
生产者消费者模型
生产者 产生数据的一方
消费者 处理数据的一方
该模型 解决双方的处理速度不同导致互相等待 从而效率低下
解决方案:1.解开耦合 使双方代码独立运行
2.在双方之间建立共享容器
问题:消费者不知道什么时候生成完毕
使用JoinableQueue
其join函数可以明确知道任务已经全部处理完成
线程
线程是执行单位,是操作系统调度运算的最小单位,是进程中具体的执行单位,一个线程就是一个固定的执行流程
进程是一个资源单位,必须包含至少一条线,系统还会自动创建一条线程 称之为主线程
线程对比进程
进程开销大 线程小
进程之间数据隔离 同一进程下线程之间数据共享
进程之间是竞争关系 线程是协作关系
进程有层级关系 线程没有
使用方法与进程没有区别
创建线程的代码可以放在任何地地方
守护线程和守护进程差不多
线程安全问题 加锁解决
死锁问题
导致程序卡死
1.对同意吧执行了多次acquire
2.同一个资源有多把锁 但是锁的钥匙被不同的进程或者线程持有
方案1:给抢锁加上固定的顺序
方案2:设置超时 放弃抢锁
递归锁
解决第一种导致死锁的问题
特点:可以多次执行acquire acquire的次数必须等于release次数才会释放信号量
限制资源可以同时被多少个线程并发访问
GIL
全局解释锁 是一个互斥锁,加在解释器上
是因为cpython中的内存管理不是线程安全的
带来的问题:导致多个线程不能并行执行,只能并发 无法利用多核CPU的优势
避免其所带来的影响
给任务分类 IO密集型 用多线程 计算密集型多用进程
不是语言问题 而是解释器问题
线程池和进程池
是一个容器 用于存放管理线程和进程
特点:线程池中的线程 运行结束也不会死亡
作用:可以限制 同时存在的线程数量 避免频繁创建销毁线程所带来的的开销 负责任务分配
同步异步
如何实现异步
多进程 多线程
状态同步
异步回调
轮训 效率低 开销大 不能及时同步