划重点1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/glw0223/article/details/88778014
Golang 之协程详解
  • 重点一
      1. 内存消耗方面
        每个 goroutine (协程) 默认占用内存远比 Java 、C 的线程少。
        goroutine:2KB
        线程:8MB

      2. 线程和 goroutine 切换调度开销方面
        线程/goroutine 切换开销方面,goroutine 远比线程小
         线程:涉及模式切换(从用户态切换到内核态)、16个寄存器、PC、SP…等寄存器的刷新等。
        goroutine:只有三个寄存器的值修改 - PC / SP / DX.
  • 重点二
    那么,协程是怎么实现的呢?
      他和线程的原理是一样的,当 a线程 切换到 b线程 的时候,需要将 a线程 的相关执行进度压入栈,然后将 b线程 的执行进度出栈,进入 b线程 的执行序列。协程只不过是在 应用层 实现这一点。但是,协程并不是由操作系统调度的,而且应用程序也没有能力和权限执行 cpu 调度。怎么解决这个问题?
      答案是,协程是基于线程的。内部实现上,维护了一组数据结构和 n 个线程,真正的执行还是线程,协程执行的代码被扔进一个待执行队列中,由这 n 个线程从队列中拉出来执行。这就解决了协程的执行问题。那么协程是怎么切换的呢?答案是:golang 对各种 io函数 进行了封装,这些封装的函数提供给应用程序使用,而其内部调用了操作系统的异步 io函数,当这些异步函数返回 busy 或 bloking 时,golang 利用这个时机将现有的执行序列压栈,让线程去拉另外一个协程的代码来执行,基本原理就是这样,利用并封装了操作系统的异步函数。包括 linux 的 epoll、select 和 windows 的 iocp、event 等。
      由于golang是从编译器和语言基础库多个层面对协程做了实现,所以,golang的协程是目前各类有协程概念的语言中实现的最完整和成熟的。十万个协程同时运行也毫无压力。关键我们不会这么写代码。但是总体而言,程序员可以在编写 golang 代码的时候,可以更多的关注业务逻辑的实现,更少的在这些关键的基础构件上耗费太多精力。
  • 重点三
调度者 调度方式
进程、线程 由内核进行调度 抢占式调度
协程 用户自己程序调度 协作式调度(非抢占式)

Golang 在 runtime、系统调用等多方面对 goroutine 调度进行了封装和处理,当遇到长时间执行或者进行系统调用时,会主动把当前 goroutine 的CPU § 转让出去,让其他 goroutine 能被调度并执行,也就是 Golang 从语言层面支持了协程。

  • 重点四
         在网络编程中,我们可以理解为 Golang 的协程本质上其实就是对 IO 事件的封装,并且通过语言级的支持让异步的代码看上去像同步执行的一样。

  • 重点五
         我们知道,协程(coroutine)是Go语言中的轻量级线程实现,由Go运行时(runtime)管理。
    什么是runtime呢?

    https://golang.google.cn/pkg/runtime/

  • 重点六
    在工程上,有两种最常见的并发通信模型:共享内存 和 消息。
    其中,锁是共享内存,因为是对同一个互斥量加锁。
    golang里对channel就是消息机制。

  • 重点七
    在UNIX中,select()函数用来监控一组描述符,该机制常被用于实现高并发的socket服务器程序。Go语言直接在语言级别支持select关键字,用于处理异步IO问题。
    原来,golang的select是从unix内核中学的。

猜你喜欢

转载自blog.csdn.net/glw0223/article/details/88778014