课程章节:5-6 如何实现协程并发?
课程讲师:Moody
课程内容:
因为协程在线程里是逐一执行的,所以,当一个协程执行时间特别长,就会阻塞当前的线程,使得线程无法执行其他的协程,而线程本身的p是包含有一个协程队列,该队列里的协程就会出现饥饿问题
为了避免时间过长导致的阻塞,会有一个方法使得协程有一个超时机制(切入时机),超时触发后,协程将会被重新放入等待队列,该协程的执行的栈帧,上下文将被保留
如果所有的线程都出现了协程队列已经满,且协程都比较耗时的情况,就会导致全局的协程队列中的协程无法进入到线程里面的情况。这就是全局饥饿问题。
全局饥饿的解决方式是,线程每切换61次协程,就从全局队列里取一个新的协程进来参与处理。
------------------------------------------
※ 切入时机
主动挂起
主动挂起是用的 gopark()方法,该方法会在末尾执行mcall方法,mcall方法会直接调用schedule(),这样协程就回到了g0栈,保存当前协程的信息( PC/SP存储到g->sched),当后续对当前协程调用goready函数时候能够恢复现场;用户不能直接调用runtime包里的gopark方法,但是可以通过time.sleep方法来间接调用gopark方法。
系统调用完成时
系统调用完成时是说,当我们想获取系统的一些硬件信息,需要调用系统底层的函数,比如netpoll这样的,那么在调用完成后,go会调用 exitsyscall方法,这个方法的底层依然是调用了mcall