教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 探索Golang协程实现——从v1.0开始

探索Golang协程实现——从v1.0开始

发布时间:2022-02-22   编辑:jiaochengji.com
教程集为您提供探索Golang协程实现——从v1.0开始等资源,欢迎您收藏本站,我们将为您提供最新的探索Golang协程实现——从v1.0开始资源

李乐

<h2>问题引入</h2>

  提起协程,你可能会说,不就go func吗,我分分钟就能创建上万个协程。可是协程到底是什么呢?都说协程是用户态线程,这里的用户态是什么意思?都说协程比线程更轻量,协程轻量在哪里呢?

  本文主要为读者介绍这些内容:

<ul><li>Golang v1.0协程并发模型——MG模型,协程创建,协程切换,协程退出,以及g0协程,重在理解协程栈切换逻辑;</li><li>为了理解协程栈,还需要简单了解下虚拟内存,函数栈帧以及简单的汇编语言;</li><li>Golang v1.0协程调度逻辑;</li><li>defer,panic以及recover底层实现原理。</li></ul>

  通过本篇文章,你将从根本上了解Golang协程。

  注:为什么选择v1.0版本呢?因为他足够的简单,不过,麻雀虽小五脏俱全;而且你会发现,即使到了现在,Golang协程实现原理,也就那么回事。v1.0版本代码可以从github上下载,分支为release-branch.go1。

<h2>基础补充</h2>

  在讲解Golang协程实现之前,还需要补充一些基础知识。理解协程,就需要理解函数栈帧,以及虚拟内存。而函数栈帧的管理,需要从汇编层次去解读。

  PS:不要怕,汇编其实很简单,不过几条指令,几个寄存器而已。

<h3>虚拟内存</h3>

  linux将内存组织为一些区域(段)的集合,如代码段,数据段,运行时堆,共享库段,以及用户栈都是不同的区域。如下图所示:

<span class="img-wrap"></span>

  用户栈,自上而下增长,寄存器%rsp指向用户栈的栈顶位置;通过malloc分配的内存通常是在运行时堆。

  想想函数调用过程,比如func1调用func2,待func2执行完毕后,还会回归道func1继续执行。该过程非常类似于栈结构,先入后出。大多数语言的函数调用都采用栈结构实现(基于用户栈),函数的调用与返回即对应一系列的入栈与出栈操作,而我们平常遇到的栈溢出就是因为函数调用层级过深,不断入栈导致的。函数栈帧如下图所示:

<span class="img-wrap"></span>

  寄存器%rbp指向函数栈帧底部位置,寄存器%rsp指向函数栈帧顶部位置。可以看到,在函数栈帧入栈时候,还会将调用方函数栈帧的%rbp寄存器入栈,以及实现多个函数栈帧的链接关系。否则,当前函数执行完毕后,如何恢复其调用方的函数栈帧?

  谁为我维护着函数栈帧结构呢?当然是我的代码了,可是我都没关注过这些啊。可以看看编译器生成的汇编代码,我们简单写一个c程序:

<pre><code class="lang-go hljs">int add(int x, int y) { return x y; } int main() { int sum = add(111,222); } </code></code></pre>

  查看编译结果:

<pre><code class="lang-go hljs">main: pushq %rbp movq %rsp, %rbp subq $16, %rsp movl $222, %esi movl $111,

您可能感兴趣的文章:
探索Golang协程实现——从v1.0开始
更改MySQL数据库名实例代码
专家教你如何有效的学习Drupal - Drupal问答
asp.net常用http状态码表
css中position相对定位和绝对定位(relative,absolute)详解
配置mysql主从复制的一点心得体会
php实现简单用户登录功能程序代码
php获取http状态码程序代码
mysql导入导出数据时中文乱码的解决办法
PHP中截取中文乱码解决办法

[关闭]
~ ~