基本概念
1.进程和线程
进程:操作系统分配资源的单位。一个在内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程可以有多个线程。
线程:操作系统分配cpu时间片的单位。进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。
2.同步和异步
同步和异步强调的是消息通信机制 (Synchronous communication/ Asynchronous communication)。
同步是在发出一个"调用"时,在没有得到结果之前,该“调用”就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由“调用者”主动等待这个“调用”的结果。异步则相反,"调用"在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在"调用"发出后,"被调用者"通过状态、通知来通知调用者,或通过回调函数处理这个调用。
3.阻塞和非阻塞
阻塞和非阻塞强调的是程序在等待调用结果(消息,返回值)时的状态。
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。 对于同步调用来说,很多时候当前线程还是激活的状态,只是从逻辑上当前函数没有返回而已,即同步等待时什么都不干,白白占用着资源。
同步异步和阻塞非阻塞区别:同步异步针对流程而言,阻塞针对调用者而言(也就是进程/线程)
Python多线程
Python的多线程很鸡肋,主要是GIL全局解释器锁,导致同一时刻只能有一个线程运行。对于面向I/O的程序来说,在程序调用I/O的时候,GIL锁会被释放,让其他线程在这个线程等待I/O的时候运行。也就是说,I/O密集型的程序比计算密集型的程序更能利用Python多线程。也可以用C语言写好计算密集型任务,然后做成动态链接库,让Python调用。调用过程中GIL锁也会被释放,从而做到多线程。
GIL最大的问题就是Python的多线程并不能利用多核CPU的优势,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。
Python多进程
Multiprocessing
要在进程间通信可以使用:
- multiprocessing.Pipe
- multiprocessing.Queue (队列的put方法和get方法都是阻塞的)
- 同步原语
- 共享变量