并发编程
在Python中,并发编程(不是并行)目前有四种方式:多进程、多线程、协程和异步
- 多进程编程在python中有类似C的os.fork,更高层封装的有multiprocessing标准库
- 多线程编程python中有Thread和threading
- 异步编程在linux下主+要有三种实现select,poll,epoll
- 协程在python中通常会说到yield,关于协程的库主要有greenlet,stackless,gevent,eventlet等实现。
进程
- 操作系统资源分配的最小单位
- 不共享任何状态
- 调度由操作系统完成
- 有独立的内存空间(上下文切换的时候需要保存栈、cpu寄存器、虚拟内存、以及打开的相关句柄等信息,开销大)
- 通讯主要通过信号传递的方式来实现(实现方式有多种,信号量、管道、事件等,通讯都需要过内核,效率低)
线程
- 操作系统调度执行的最小单位
- 共享变量(解决了通讯麻烦的问题,但是对于变量的访问需要加锁)
- 调度由操作系统完成(由于共享内存,上下文切换变得高效)
- 一个进程可以有多个线程,每个线程会共享父进程的资源(创建线程开销占用比进程小很多,可创建的数量也会很多)
- 通讯除了可使用进程间通讯的方式,还可以通过共享内存的方式进行通信(通过共享内存通信比通过内核要快很多)
协程
- 调度完全由用户控制
- 一个线程(进程)可以有多个协程
- 每个线程(进程)循环按照指定的任务清单顺序完成不同的任务(当任务被堵塞时,执行下一个任务;当恢复时,再回来执行这个任务;任务间切换只需要保存任务的上下文,没有内核的开销,可以不加锁的访问全局变量)
- 协程需要保证是非堵塞的且没有相互依赖
- 协程基本上不能同步通讯,多采用异步的消息通讯,效率比较高
总结
- 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度
- 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)
- 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度