所有的代码就是?线程来执?的,?如有?段线程执?的时间?,有起点 A 和终点 B,执??段 Logic ?户代码,执?到某点时需要做系统调?,做系统调?的时候就会在这?点阻塞,然后执?序就进?系统内核状态,?户线程就会在这地? Block,剩下来的时间?就交给系统内核去执?了。
假如?户线程被阻塞住的时候,系统调?不使?剩下来的时间?,?把系统调?变成操作系统内核的异步调?,那么它所使?的时间?实际上是操作系统内部的?些时间?,后??段?户线程的时间?就被空出来了,空出来的话阻塞那这个时间???浪费掉了,为什么??浪费掉了?第?种可能就是看使?什么样的阻塞?式,?种?式阻塞在那?直等?直等什么都不干,另外?种操作系统觉得剩下来时间?拿?交给别的程序或者线程去执?,对于我们进程执?来说这很显然就是性能损失。
【协程】所以能不能有这样的?种模式,当程序执?线程A执?到?点的时候被阻塞了,然后发??次系统调?,让
这个系统调?异步执?,剩下来的时间?不打算交回去,完成?次调度把这段时间?交给线程B执?,当系
统调?完成的时候有很多机制实现唤醒,?如说select、epoll这样的?些机制,唤醒把结果返还给A。这样的话可以在同?个线程执?并发多个任务,这些并发任务实际上是在?户态完成的和操作系统?关
概念
利?异步机制利???在?户态实现这种调度机制把阻塞的那段时间抢回来?来执?其他的任务,当 B 任务执?结束的时候下次再执?的时候去会检查epoll返回的事件,然后把A的结果返还给A,这样?来我们在?户空间实现多任务的调度?多任务调度是发?在?个线程上的,我们把这种机制称之为协程.
因为操作系统调度以系统线程为单位的,但是我们在操作系统以外?户空间再实现?次调度,它每次浪费的时间?都捡回来尽可能去执?我们的代码,我们可以把这种机制称之为协程,就是它?线程粒度更?,因为它实际在线程上把线程的时间?划分成多个块在线程上再去执?多个任务,但是协程很显然是串?的它不是真正意义上的并?,实际上是执?A任务当A任务阻塞的时候然后唤醒B任务,B任务完了以后可能做?次检查看 A 的结果回没回来,很显然它这种切换来实现多任务并发,协程本质是串?的
原理
他和线程的原理是一样的,当a线程切换到b线程的时候,需要将a线程的相关执行进度压入栈,然后将b线程的执行进度出栈,进入b的执行序列。协程只不过是在应用成实现这一点。
协程是基于线程的。内部实现上,维护了一组数据结构和n个线程,真正的执行还是线程,协程执行的代码被扔进一个待执行队列中,有这n个线程从队列中拉出来执行。这就解决了协程的执行问题。那么协程是怎么切换的呢?答案是:golang对各种io函数进行了封装,这些封装的函数提供给应用程序使用,而其内部调用了操作系统的异步io函数,当这些异步函数返回busy或bloking时,golang利用这个时机将现有的执行序列压栈,让线程去拉另外一个协程的代码来执行,基本原理就是这样,利用并封装了操作系统的异步函数。包括linux的epoll,select和windows的iocp,event等。