目录

Goroutine

go对并发编程是原生支持,语言级别

1 协程是轻量级"线程”

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func main() {
  //开一千个协程
	for i:=0;i<1000;i++{
		go func() {
			for {
				fmt.Printf("print from go routine %d\n",i)
			}
		}()
	}
	time.Sleep(time.Millisecond)
}
  • 非抢占式多任务处理,由协程主动交出控制权

    线程会被操作系统任意切换,协程是主动交出控制权减少因上下文切换而带来的资源消耗

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    package main
      
    import (
      "fmt"
      "time"
    )
      
    func main() {
      var a = make([] int,10)
      for i:=0;i<10;i++{
          go func(i int) {
              for {
                  a[i] ++
              }
          }(i)
      }
      time.Sleep(time.Millisecond)
      fmt.Println(a)
    }
      
    ### 程序并没有输出因为程序一直给a[i] +1 ###
      
    // 解决方式是在go routine的for中加入
      
    // 交出CPU控制权,让出cpu时间片
      runtime.Gosched()
    
  • 编译器/解释器/虚拟机层面的多任务

    线程是操作系统级别的多任务

  • 多个协程可能在一个或多个线程上运行

2 goroutine

https://s1.ax1x.com/2020/09/13/w04Iaj.png

  • 任何函数只要加上go就能送给调度器运行

  • 不需要在定于时区分是否是异步函数

  • 调度器会在合适的点进行切换,不用程序员显示指定(类似于抢占式多任务处理)

    • I/O,select
    • channel
    • 等待锁
    • 函数调用(有时)
    • runtime.Gosched()
    • 仅供参考,不能保证切换,也不能保证其他地方不切换
  • 使用 -race来检测数据访问冲突

    1
    
    go run -race main.go