(四十一)golang--goroutine

时间:2022-07-23
本文章向大家介绍(四十一)golang--goroutine,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

首先得了解:

  • 进程
  • 线程
  • 并发
  • 并行

Go协程和Go主线程:

主线程:相当于进程;直接作用于cpu上,是重量级的,是物理态的;

协程:相当于轻量级的线程;由主协程开启,是逻辑态的;

Go协程的特点:

  • 有独立的栈空间
  • 共享程序堆单元
  • 调度由用户控制
  • 协程是轻量级的线程

举个例子:

package main

import (
    "fmt"
    "strconv"
    "time"
)

func test() {
    for i := 0; i < 20; i++ {
        fmt.Println("test() hello world" + strconv.Itoa(i))
        time.Sleep(time.Second)
    }
}

func main() {
    go test()
    for i := 0; i < 10; i++ {
        fmt.Println("main() hello world" + strconv.Itoa(i))
        time.Sleep(time.Second)
    }
    fmt.Println("finish")
}

main中的for和test中的for同时运行,当主协程main打印了10次后,不管test协程中打印了几次,test协程都会结束掉。

主协程和协程的关系:

MPG模式:

  • M:主协程,物理协程;
  • P:协程所需上下文;
  • G:协程

说明:

(1) 当前程序有三个M,如果三个M都在同一个cpu上运行,就是并发;在不同cpu上运行,就是并行;

(2)灰色代表协程队列;

(3)go的协程是轻量级的线程,是逻辑态的;

(4)其它程序中的多线程,往往是内核态的,比较重量级;

调度模型:

(1)分成两个部分来看;

(2)原来的M0主协程正在执行G0协程,另外有三个协程正在队列中等待;

(3)如果G0协程阻塞,比如读取文件或数据库等;(也就是说不知道什么时候可以完成)

(4)这时候就会创建一个M1主协程(也可能是从已有的线程池中取出M1),并且将等待的三个协程挂到M1下开始执行,M0的主线程下的G0仍继续执行;

(5)等到G0不阻塞了,M0会被放置到空闲的主线程继续执行,同时G0又会被唤醒;

设置使用几个cpu: