go基础知识-goroutine

69 阅读2分钟

什么是goroutine?

goroutine在go中作为协程存在,是go并发处理的主要手段。其并发程序主要基于CSP并发模型实现。

特点

  1. 有着轻量级的优势,初始化一个goroutine只有2KB的内存空间,使得上下文的切换代价非常小。
  2. 在一个goroutine中,每一个结构体G中存在一个sched的属性保存上下文,这样goroutine可以轻易来回切换。
  3. 上下文是在用户态下发生的,不必进入内核,只保存当前goroutine下的PC,SP等少量信息,所以速度很快。

如何使用?

goroutine的使用很简单,只需要使用go关键字即可启动,如下:

go func() {
    fmt.Println("hello")
}()

如何调度实现的?

goroutine的调度是通过运行时(runtime)管理,采用GMP调度模型。

  • G(goroutine):go协程,包含自己的栈、程序计数器等信息。
  • M(machine):os内核线程,用于执行G。
  • P(processor):处理器,一般保存当下goroutine运行的上下文环境,管理goroutine队列做调度。
  • LRQ:本地运行队列。
  • GRQ:全局运行队列。

调度过程:

  1. 某个线程尝试创建G对象,该G对象被安排到本地队列LRQ中,如果LRQ队列满了,则被分配到全局队列GRQ中。
  2. 尝试获取当前线程的M,如果没法获取,就会从空闲的M列表找一个出来,如果空闲列表也没有,就会创建一个M,然后绑定G到P运行。
  3. 执行G,完成后退出。

Go什么时候发生阻塞?阻塞时,调度器会怎么做。

  • 用于原子、互斥量或通道操作导致goroutine阻塞,调度器将把当前阻塞的goroutine从本地运行队列LRQ换出,并重新调度其它goroutine;
  • 由于网络请求IO导致的阻塞,Go提供了网络轮询器(Netpoller)来处理,后台用epoll等技术实现IO多路复用。