并发编程
基础概念
并行和并发
- 并行 同一时刻,多个任务在多个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)从程序里领取任务