python的并发编程学习
并发编程
基础概念
并行和并发
- 并行 同一时刻,多个任务在多个cpu中被执行
- 并发 同一时间段内,多个任务交替执行在cpu上
异步和同步- 异步 : 两个任务(当前所在的代码,和另一个独立的任务)之间没有明确的先后关系
一个任务的继续并不影响到另一个任务的执行 - 同步 : 两个任务之间有明确的先后关系
一个任务的继续必须依赖于上一个任务的结果
- 异步 : 两个任务(当前所在的代码,和另一个独立的任务)之间没有明确的先后关系
阻塞和非阻塞
- 阻塞 :等待io操作结束
- 非阻塞 :不等待io操作结束
进程和线程和协程-
进程(multiprocess) 操作系统中资源分配的最小单位,最大特点:资源独立;能利用多核;有数据安全问题: 同时操作数据库,操作文件占用操作系统资源开销大
-
线程(threading)操作系统中cpu调度的最小单位,资源共享;能利用多核;有数据安全问题:同时处理内存就会出现问题占用的操作系统资源相对,最大特点 处理并发
-
协程(gevent) 操作系统不可见,资源共享,不能利用多核,本质是一条线程,没有数据安全问题:无占用的操作系统资源相当于一条线程
-
进程和程序 :运行中的程序是一个进程
进程的三状态 :就绪 运行 阻塞
-
GIL锁 CPython解释器中管理线程的机制 保证了CPython解释器中
多个线程 只有一个线程在同一时间点能访问cpu
由于CPython解释器导致了我们不能充分利用多线程来访问多个CPU
-
多进程 : 帮助我们在Cpython解释器下利用多核
-
多线程 : 当我们不确定io操作或者python语言没有给这个io操作设置协程识别的语法的时候就需要使用线程了
-
协程 : 在单线程中,有n个任务,这n个任务如果同步执行,那么所有的io时间是累加在一起的, 协程永远不会数据不安全 因为协程是由程序员控制的,而程序员控制的只能是代码,而不是CPU指令
协程的原理完成一个任务,遇到io之后,能够切换到另一个任务执行,所有的io操作的时间还能做其他任务的执行\这样就可以通过一条线程完成多个任务,协程的本质:就是一条线程 底层切换也是有开销的,切换的开销就和函数调用的开销是一样的
如果是 += *= /= -= 都存在数据不安全的问题 l[0] += 1
如果是 append extend pop remove不会存在数据不安全的问题
#进程代码
from multiprocessing import Process
def target_func(a1,a2,a3): #必须是元组
pass # 计算密集型的代码,高计算代码
p = Process(target=target_func,args=(1,2,3))
p.daemon = True # 守护进程 守护到主进程代码结束(是谁随着主进程代码结束,并不是随着主进程的结束而结束,因为守护进程也是主进程的一个子进程,守护进程的资源需要主进程来回收),和子进程无关,并且一定要在start之前
p.start()#开启一个进程
p.join()#等待进程任务
#进程的流程
#主进程的代码结束
#阻塞
#等待其他非守护进程结束
#子进程全部结束
#回收子进程的资源
#主进程结束
-
锁 (lock)他是最重要,用法:共同访问某一文件/共享变量的时候,数据库
互斥锁 :在一条线程只可以require一次
递归锁 :在一条线程可以连续require多次
-
事件(event)set(True) clear(False)--->决定wait是否等待 这些全都是围绕着一个flag来说的,
-
信号量(Semaphore) 控制某一段代码同一时刻只被n个线程\进程执行
-
管道 进程之间的通信(不安全)但是速度快,因为他不加锁
-
队列 进程之间的通信(安全),不依赖第三方工具,消息队列和程序耦合度太高
-
进程池(pool)从程序里领取任务