goroutine | 青训营笔记

49 阅读2分钟

这是我参与「 第五届青训营 」伴学笔记创作活动的第 2 天 整理了goroutine相关的知识内容,以及操作系统基础知识的回顾

操作系统知识回顾

进程与线程
  • 进程就是程序程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位。
  • 线程是进程的一个执行实例,是程序执行的最小单元,它是比进程更小的能独立运行的基本单位。
  • 一个进程可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行。
  • 一个程序至少有一个进程,一个进程至少有一个线程。
并发、并行、串行
  • 串行任务依次执行,第一个任务执行完才会执行第二个
  • 并行所有任务同步执行且互不干扰
  • 并发任务交替执行但只有一个任务在运行,允许互相干扰

goroutine

  • Go主线程(有程序员直接称为线程/也可以理解成进程):一个Go线程上,可以起 多个协程,你可以这样理解,协程是轻量级的线程。
  • Go协程的特点:有独立的栈空间,共享程序堆空间,调度由用户控制,协程是轻量级的线程
goroutine实例

helloword实例

func test() {
    for i := 1; i <= 10; i++ {
        fmt.Println("goroutine", i)
        time.Sleep(time.Second)
    }
}
func main() {
    go test() // 开启协程

    for i := 1; i <= 10; i++ {
        fmt.Println("main", i)
        time.Sleep(time.Second)
    }
}

main 1 goroutine 1 goroutine 2 main 2 main 3 goroutine 3 main 4 goroutine 4 goroutine 5 main 5 main 6 goroutine 6 goroutine 7 main 7 main 8 goroutine 8 goroutine 9 main 9 main 10 goroutine 10

阶乘实例

var (
    myMap = make(map[int]int, 10)
    lock sync.Mutex // 互斥锁
)

func test(n int) {
    res := 1
    for i := 1; i <= n; i++ {
        res *= i
    }
    lock.Lock()
    myMap[n] = res
    lock.Unlock()
}

func main() {
    for i := 1; i <= 20; i++ {
        go test(i)
    }
    
    lock.Lock()
    for i, v := range myMap {
        fmt.Printf("map[%d]=%d\n", i, v)
    }
    lock.Unlock()
}
goroutine MPG调度模式
  • M:操作系统的主线程(是物理线程)
  • P:协程执行需要的上下文
  • G:协程

image.png

当前程序有三个M,如果三个M都在一个cpu运行,就是并发,如果在不同的cpu运行就是并行M1,M2,M3.正在执行一个G,M1的协程队列有三个,M2的协程队列有3个,M3 协程队列有2个从上图可以看到: Go的协程是轻量级的线程,是逻辑态的,Go可以容易的起上万个协程其它程序c/java的多线程,往往是内核态的,比较重量级,几千个线程可能耗光cpu