1.多线程、多进程、多协程
进程:一个运行的程序,进程是系统调度和分配的最小单位,拥有自己独立的空间内存,进程之间不共享资源。
线程:调度执行的最小单位,依赖于进程,一个进程至少有一个线程,并且同一个进程内的线程之间共享资源,大大提升了程序运行速度,切换由系统调度。
协程:一种用户态的轻量级线程,切换由用户调度,拥有自己的上下文和栈,切换时将寄存器上下文和栈保存在别的地方,切换回来时,恢复先前的寄存器上下文和栈,直接操作栈基本没有内核的消耗,
所以切换速度较快。
2.多线程竞争
线程是独立的,多线程之间共享资源,当多个线程访问同一资源时,数据同时被多个线程所占有,导致数据混乱,即数据不安全。为了解决这个问题,那就有了锁。
锁的好处,确保了某段代码只能从头到尾都只能被一个线程占有。
锁的坏处,阻止了线程的并发性,大大降低了程序的运行速度。
3.锁
锁是python提供的对多线程进行控制的对象,有互斥锁,可重入锁,死锁。
死锁,若干子线程在资源竞争时,都在等待对方解除对某一资源的占用,导致程序无法运行下去。
GIL锁,全局解释器锁(golbal interpreter lock)只有在cpython中存在,作用是限制多线程的同时执行,同一时间只允许一个线程的运行。在python中常使用协程来代替进程,协程是轻量级的进程,
并且由用户控制。
互斥锁,同一个进程中多线程共享资源,为了达到数据安全的效果,同一时间只能有一个线程去访问某一资源,后续的线程必须等待前一个线程访问过后才能继续访问这一资源。
4.同步,异步,非阻塞
任务
同步,多个任务按顺序执行
异步,多个任务同时执行,并且存在某个任务需要另一个任务执行之后的结果作为条件,这叫回调
代码
阻塞,执行卡住,不再继续往下执行
非阻塞,执行不会卡住,可以继续执行
5.僵尸进程,孤儿进程
1.僵尸进程,子进程比父进程结束的早,没有被收回,且没有释放所占有的资源
2.孤儿进程,父进程结束的比子进程早,子进程还在运行,这类进程后续会被init进程接管,完成状态收集工作
3.对僵尸进程的解决方法 1.fork两次让孙子进程去执行子进程的任务
2.用wait()使父进程阻塞
3.使用信号量,signal handler 中调用waitnid
6.进程
进程是程序的一次动态执行过程
创建,准备,运行,阻塞,结束
7.python中多线程与多进程的使用场景
多进程cpu密集型操作
多线程io密集型操作
8.协程
asyncio
实现的功能
1.异步网络操作
2.并发
3.协程
关键字说明
1.event_loop 事件循环,程序开启一个无限循环,当实现一定条件时,执行此事件
2.coroutine 协程,指async关键字定义的函数,调用不会立即执行,而是会返回一个协程对象,只有注册到事件循环中后,由事件循环调用
3.task任务 对协程对象的属性和状态进行包装
4.future 与task没有本质上的区别
5.async/await关键字 async定义协程函数,await用于调用挂起阻塞的异步调用接口
一个协程对象的定义
async def coroutine():
pass
c = conroutine()
pool = asyncio.get_event_loop() #创建事件循环
pool.run_until_complete(c) #将协程对象注册到事件循环中,并开启事件循环
一个task对象的定义
loop = asyncio.get_event_loop()
task = loop.create_task(conroutine) #创建一个task任务,包装协程对象,保存了协程运行后的状态,用于未来获取协程的结果,也可通过asyncio.ensure_future(conroutine)创建task任务
pool.run_utile_complete(task)
task加入到事件循环之前状态为pending,之后为finished
对task任务添加回调函数
def callback(future):
pass
task.add_done_callback()
await 挂起耗时操作或阻塞,将协程的控制权交出,以便事件循环调用其他协程
关于并发与并行
并发:同时具有多个活动的系统
并行:用多个并发使一个系统运行的更快速。并行可以在操作系统的多个抽象层次运用
通俗讲,并发,多个任务需要同时进行,并行,同一时刻有多个任务执行。
并发
tasks = [
asyncio.ensure_future(coroutine1),
asyncio.ensure_future(coroutine2),
asyncio.ensure_future(coroutine3)
]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks)) #asyncio.gather(*tasks)