一: 进程的概念:(Process)
进程就是正在运行的程序,它是操作系统中,资源分配的最小单位.
资源分配:分配的是cpu和内存等物理资源
进程号是进程的唯一标识
同一个程序执行两次之后是两个进程
进程和进程之间的关系: 数据彼此隔离,通过socket通信
二:并行和并发
并发:一个cpu同一时间不停执行多个程序
并行:多个cpu同一时间不停执行多个程序
三:cpu的进程调度方法
# 先来先服务fcfs(first come first server):先来的先执行
# 短作业优先算法:分配的cpu多,先把短的算完
# 时间片轮转算法:每一个任务就执行一个时间片的时间.然后就执行其他的.
# 多级反馈队列算法
越是时间长的,cpu分配的资源越短,优先级靠后
越是时间短的,cpu分配的资源越多
### 进程三状态图
(1)就绪(Ready)状态
只剩下CPU需要执行外,其他所有资源都已分配完毕 称为就绪状态。
(2)执行(Running)状态
cpu开始执行该进程时称为执行状态。
(3)阻塞(Blocked)状态
由于等待某个事件发生而无法执行时,便是阻塞状态,cpu执行其他进程.例如,等待I/O完成input、申请缓冲区不能满足等等。
四:同步 异步 / 阻塞 非阻塞
场景在多任务当中
同步:必须等我这件事干完了,你在干,只有一条主线,就是同步
异步:没等我这件事情干完,你就在干了,有两条主线,就是异步
阻塞:比如代码有了input,就是阻塞,必须要输入一个字符串,否则代码不往下执行
非阻塞:没有任何等待,正常代码往下执行.
# 同步阻塞 :效率低,cpu利用不充分
# 异步阻塞 :比如socketserver,可以同时连接多个,但是彼此都有recv
# 同步非阻塞:没有类似input的代码,从上到下执行.默认的正常情况代码
# 异步非阻塞:效率是最高的,cpu过度充分,过度发热
五:守护进程
#可以给子进程贴上守护进程的名字,该进程会随着主进程代码执行完毕而结束(为主进程守护)
(1)守护进程会在主进程代码执行结束后就终止
(2)守护进程内无法再开启子进程,否则抛出异常(了解)
六: 锁(Lock)
lock.acquire()# 上锁
lock.release()# 解锁
#同一时间允许一个进程上一把锁 就是Lock
加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲速度却保证了数据安全。
#同一时间允许多个进程上多把锁 就是[信号量Semaphore]
信号量是锁的变形: 实际实现是 计数器 + 锁,同时允许多个进程上锁
# 互斥锁Lock : 互斥锁就是进程的互相排斥,谁先抢到资源,谁就上锁改资源内容,为了保证数据的同步性
# 注意:多个锁一起上,不开锁,会造成死锁.上锁和解锁是一对.
七.Semaphore(信号量)
信号量Semaphore是一个计数器,控制对公共资源或者临界区域的访问量,信号量可以指定同时访问资源或者进入临界区域的进程数。每次有一个进程获得信号量时,计数器-1,若计数器为0时,其他进程就停止访问信号量,一直阻塞直到其他进程释放信号量。
上述讲的Lock,属于互斥锁,也就是一把钥匙配备一把锁,同时只允许锁住某一个数据。而信号量则是多把钥匙配备多把锁,也就是说同时允许锁住多个数据。
八:事件(Event)
# 阻塞事件 :
e = Event()生成事件对象e
e.wait()动态给程序加阻塞 , 程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值是False]
# 如果是True 那就加阻塞
# 如果是False 就不不加阻塞
# 控制这个属性的值
# set()方法 将这个属性的值改成True
# clear()方法 将这个属性的值改成False
# is_set()方法 判断当前的属性是否为True (默认上来是False)
九:Queue队列
#先进先出 原则
进程Queue:建立一个共享的队列(其实并不是共享的,实际是克隆的,内部维护着数据的共享),多个进程可以向队列里存/取数据)
十. 生产者与消费者模型
(1)为什么要使用生产者消费者模型
生产者指的是生产数据的任务,消费者指的是处理数据的任务,在并发编程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
(2)什么是生产者和消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题,生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
这个阻塞队列就是用来给生产者和消费者解耦的
十一:JoinableQueue
1. 概述
JoinableQueue 与Queue一样也是multiprocessing模块中的一个类,也可以用于创建进程队列。
JoinableQueue 创建可连接的共享进程队列,队列允许队列的消费者通知生产者,队列数据已被成功处理完成。通知过程是使用共享的信号和条件变量来实现的。
2.常用方法与属性
(1)put 存入
(2)get 获取
JoinableQueue除了与Queue相同的方法之外,还具有2个特有的方法
(3)q.task_done()
消费者使用此方法发出信号,表示q.get()返回的项目已经被处理完成。如果调用此方法的次数大于从队列中删除的项目数量,将引发ValueError异常。
每次get一次数据,就执行一次task_done(),可以让中间变量的值减1
(4)q.join()
判断如果队列里面还有值,默认是要加阻塞的。阻塞将持续到为队列中的每个项目均调用q.task_done()方法为止。
task_done 与 join 通过一个中间变量统计列表元素个数
每放入一个值,队列元素个数加1
通过task_done让当前队列的元素数量减1
最后join查找统计队列的这个变量,如果是0,才不会添加阻塞,放行
后面的文章将对进程一一举例学习