多线程
python的多线程由于全局锁并不能并行,而是是单线程执行的分时复用模式。
- 线程A占用CPU,获得GIL锁。
- 遇到IO操作,中断,则释放锁。
- 没遇到IO,则执行1000字节指令(py2)或者执行运行时间15ms,释放。
- 根据竞态原则,抢到的线程会占用cpu,从新获得GIL。
每个线程可能会由各种计算和IO操作组成,再整个执行过程中,cpu会因为上述原因不断地在各个线程之间切换,使得线程在执行IO的时候,cpu不会空等它结束而是去服务其他线程,这样就造成了多线程像是并行一样的效果。
协程
协程虽然叫微线程,但并不是把线程再拆分,它的本质是单线程,是在单线程上运行的多个子程序。python3是用asyncio来实现协程的。
- 定义协程:函数前写有async的函数,类型就是coroutine。它不能被直接调用,而是需要await使用。
import asyncio async def test(): await asyncio.sleep(1) print("123456") print(type(test()) # output:<class 'coroutine'>
- 阻塞I/O操作的时候,会切换另一个子程序。
- 或者遇到awaitable的事件(人为定义的中断),会切换另一个子程序。
总结
-
多线程切换受内核影响,有一定的规则,而且切换开销大。协程理论上不受数量约束,越多并发的效果越好。
-
同样是并发编程,协程拥有良好的可设计性,可人为设置中断让程序按照自己的思路执行。多线程因为是竞态无法做到可控。
-
但协程毕竟是单线程操作,如果是IO密集型工作,也难以设计的那么精细,建议还是多线程搞起来比较暴力快速。比如爬虫和后续的处理。