协程是应用层的线程。
应用层是相对于内核层而言,是操作系统的概念,对应的是cpu的运行级别。操作系统的核心代码运行的ring0级别,应用程序的代码运行在ring3级别。内核与应用层的级别设置保证了一些高权限的操作只有内核代码能做,应用程序要使用这些功能必须通过调用操作系统的API(linux上称为系统调用)来调用内核的代码。这个调用会导致cpu从ring3到ring0的上下文切换,这个切换是耗费一些cpu时间的。
线程是操作系统的内核对象,多线程编程时,如果线程数过多,就会导致频繁的上下文切换,这些cpu时间是一个额外的耗费。所以在一些高并发的网络服务器编程中,使用一个线程服务一个socket连接是很不明智的。于是操作系统提供了基于事件模式的异步编程模型。用少量的线程来服务大量的网络连接和I/O操作。但是采用异步和基于事件的编程模型,复杂化了程序代码的编写,非常容易出错。因为线程穿插,也提高排查错误的难度。
协程,是在应用层模拟的线程,他避免了上下文切换的额外耗费,兼顾了多线程的优点。简化了高并发程序的复杂度。举个例子,一个高并发的网络服务器,每一个socket连接进来,服务器用一个协程来对他进行服务。代码非常清晰。而且兼顾了性能。
那么,协程是怎么实现的呢?
他和线程的原理是一样的,当a线程切换到b线程的时候,需要将a线程的相关执行进度压入栈,然后将b线程的执行进度出栈,进入b的执行序列。协程只不过是在应用成实现这一点。
但是,协程并不是有操作系统调度的,而且应用程序也没有能力和权限执行cpu调度。怎么解决这个问题?