981377660LMT / ts

ts学习
6 stars 1 forks source link

有栈协程、无栈协程、各种协程的区别、go关键字的理解 #265

Open 981377660LMT opened 1 year ago

981377660LMT commented 1 year ago

Golang、Kotlin、C#、JS、Python 等都有协程,市面上的协程有什么本质上的区别? - readcopy 的回答 - 知乎 https://www.zhihu.com/question/502314022/answer/2343470555

981377660LMT commented 1 year ago

https://www.bilibili.com/video/BV1VM411C73z image

image

go程可以利用多核,加速 CPU Bound的任务

  1. 离,hand off 如果某个G在M处阻塞,那么队列就会搬家(P离开M),使用新的调度器P在原来的CPU上继续工作 image
981377660LMT commented 1 year ago
981377660LMT commented 1 year ago

  1. CPS Continuation-Passing Style(CPS)是一种编程风格或转换方法,用于控制流的处理。 在 CPS 中,程序的计算结果不是直接返回给调用方,而是通过将控制权传递给一个称为"continuation"(续延)的函数来进行处理。这种方式将控制流从函数内部延续到外部。 CPS 的核心思想是将控制流明确地表示为函数调用的序列,以及在每个函数调用之间传递控制的 continuation 函数。
  2. 协程的本质:非抢占式多任务 有让出无抢占,就叫协程。 yield/await 都是让出执行权的方式。
  3. 抢占式多线程减去抢占就等于协程,但是因为直接使用内核态多线程是不能阻止抢占的,所以这个思路实现的协程基本上都是内核线程池加协作式用户态线程。

    抢占是一个很低效的操作

  4. 有调度的有栈协程就是 goroutine(的无抢占版),约等于用户态线程去掉抢占。

协程有两代:

第一代是操作系统那帮人搞的,这代协程的本质是用户态线程切换, 在用户态实现了线程调度。 这代协程最终成熟形态是线程池对大量任务的执行。 开源的实现就是 golang (但是丢弃了一些协程的优势,带来的复杂度使得使用协程跟使用线程具有相同的心智负担,有抢占就和线程没区别了:同步和竞争条件)

第二代协程是 async/await,来自于做并行计算那帮人。正式名称叫 Join calculus,概念本身来自于 caml 社区。 这代协程本质上解决的问题是同步操作时,CPU 或线程浪费的问题。 二代协程和一代的区别在于编程时候是否以类似同步方式开发的,能否降低开发人员心智负担。

不管是一代协程还是二代协程,性能都没有线程+callback 高


如何评价 stackless 和 stackful? 一般不建议讨论协程的时候提起 stack,显得基础不够扎实: stack 并不是 coroutine 独有的实现问题,它实际上是 routine/subroutine 的实现问题。只要是函数调用,实现上就有需要 stack 问题


golang: 有栈协程 js/python: 无栈协程


至于说协程减少上下文切换,这是当然的,因为都是同一个线程,同一个线程内当然减少了上下文切换。