进程
2020-09-22 21:32:37 0 举报
AI智能生成
python 进程 和 线程
作者其他创作
大纲/内容
进程的概念
进程是正在运行的程序,它是操作系统分配资源的最小单位
资源分配:分配的是CPU和内存等物理资源
同一个程序执行两次之后是两个进程
进程和进程之间数据彼此隔离,通过socket通信
进程号
进程的唯一标识,用os.getpid()获取进程号,os.getppid()获取父进程号
进程号是进程的唯一标识
开启多进程
from multiprocessing import Process 从multiprocessing模块导入Process类
if __name__ == '__main__": 开辟多进程一定要加上,不然会报错
p = Process(target = func, args = (a,b...)),创建进程对象 参数target是要执行的任务(函数名),args是函数的参数,要用元组
p.start() 开始进程
进程是异步的,哪个程序跑的快就执行哪个,通常主进程会跑到子进程的前面,
因为执行子进程之前,CPU要分配资源。但是主进程即使先执行完了,它也会等所有子进程结束之后再回收系统资源。
同步
p.join(),为了保证子主进程同步,在start之后加上该句。主进程会等所有加了join的子进程结束之后,再执行。
如果要加join的子进程很多,可以让所有子进程start之后,加入列表,通过循环列表,逐个加上join
守护进程
p.daemon() = True,守护进程,
该语句加在start()之前。主程序结束时会默认等待所有子程序结束后再回收资源。但是守护进程例外,主程序结束时,守护进程也就终止了。通常用在服务器的监控报活
用类定义进程
锁
锁定数据,保证数据在修改的时候不会出错
Lock 互斥锁
进程之间数据隔离,需要加锁,防止数据最乱改,加锁之外进程是异步的,加锁的时候进程是同步的
from multiprocessing import Lock
lock = Lock() 拿到1把锁
lock.acquire() 上锁
lock.release() 解锁,上锁解锁是一对,只上锁不解锁,会死锁
with lock: 执行语句。 可以将简化上锁解锁步骤
Semaphore 互斥锁
Lock只能上一把锁,Semaphore上多把锁
from multiprocessing import Semaphore
sem = Semaphore(4) 拿到四把锁
sem.acquire() 上锁
sem.release() 解锁,上多少把锁就要解多少锁
事件
Event 事件
事件相当于开关,可以阻塞进程,达到放行的条件(阻塞时间到,放行开关打开)才放行
from multiprocessing import Process
e = Event() 事件对象
e.wait() 加阻塞,没有时间限制,除非遇到放行开关,不然不放行。e.wait(2) 加2秒阻塞,2秒后放行。
e.is_set() = False 有阻塞不放行,默认有阻塞
e.is_set() = True 放行
e.set() 更改e.is_set()的值为True,打开放行开关
e.clear()更改e.is_set()的值为False,关闭放行开关
e.wait()加在要被阻塞的代码之前,后面的代码通过e.is_set()的值来决定是否可以执行。e.is_set()的值通过e.set()和e.clear()设置
队列
Queue
存取数据,实现数据的共享
IPC(Inter_Process Communication) 进程间通信,有两种方式,PIPE和Queue。Queue数据先进先出。进程之间可以通过queue交换数据
from multiprocessing import Queue
q = Queue() 拿到队列对象,可以通过Queue(n)来限制队列的长度。
q.put(sth) 往队列存值,如果队列限制的长度是3个,塞了4个值,就会形成阻塞,一直等到队列有空位了,再继续。
不推荐使用 q.put_nowait()它在linux下的兼容性很差,找不到空位就不等了,直接抛出异常。
q.get(sth) 从队列取值,如果队列没有值还在取,就会形成阻塞,一直等到取到值才放行。
不推荐使用 q.get_nowait()它在linux下的兼容性很差,取不到值就不等了,直接抛出异常。
生产者消费者模型
生产者负责往队列塞数据,q.put()
消费者负责从队列取数据,q.get()
理想的生产者消费者模型,追求彼此的速度相对均匀。
比如在爬虫中,1号进程负责抓取页面的内容,也就是数据(页面内容)的生产者,2号进程负责匹配页面内容,也就是数据(页面内容)的消费者。
通过Queue实现,适用于只有一个生产者,一个消费者的情形。通过生产者在结束的时候put一个None,消费者收到None退出循环,结束所有进程。
q = Queue()
q.put()
q.get()
通过JoinableQueue实现,适用于有多个生产者,多个消费者的情形。
jq = JoinableQueue()
q.put()
q.get()
q.join()
队列的阻塞,要队列中没有值了才能放行
q.task_done()
队列中的值取走一个,队列中的计数减一。配合join使用
p1是生产者进程,P2是消费者进程,p1循环五次,也就是开5个进程,放5个值到队列。设置p1为同步程序,p1执行完后,主程序再执行。设置p2是守护进程,主程序结束的时候会带走P2。但是在主程序结束前加上队列阻塞q.join()确保队列值清空之后才会往下执行代码。这样就能保证p2一定能取到所有p1放进去的值。
Manager
用于在进程之间共享字典和列表数据
from multiprocessing imort Process,Manager,Lock
m = Manger() 拿到manager对象
data = m.dict(dict) 通过m.dict 或者 m.list()创建一个可以在进程间通信的字典
多进程对数据进行修改的时候,还是要加锁,确保数据正确
执行方式
并行和并发
并发
一个CPU同一时间不停执行多个程序
并行
多个CPU同一时间不停执行多个程序
同步和异步
同步
一条主线
同步阻塞
效率最低,CPU利用不充分
同步非阻塞
异步
一个CPU在进程之间不停的切换
异步阻塞
异步非阻塞
效率最高,易导致CPU过热,从而CPU降频,影响执行速度
CPU的调度方法
先来先服务
first come first serve
短作业优先
时间片轮转
多级反馈
上面3中的综合
线程
概念
线程:cpu执行程序的最小单位
负责在进程拿到的资源下干活
进程:资源分配的最小单位
负责拿资源
1个进程下可以有多个线程,多线程共享同一份进程资源
Python中线程可以并发但是不可以并行,
同一个进程下的多个线程只能被一个CPU执行。
线程的用法和进程差不多,但是线程执行效率远远超出进程,因为线程不需要等待CPU分配资源
基本使用
from threading import Thread
进程一定要加的 if __name__ == '__main__': 线程可以不加
t = Thread(target = func, args = (参数1,参数2...)) 拿到线程对象
t.start() 执行线程
t.join() 同步线程
子主题
子主题
子主题
0 条评论
下一页