Go goroutine

Posted ycx95

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go goroutine相关的知识,希望对你有一定的参考价值。

2018-07-25 16:40:10

goroutine 

Go语言协程

技术分享图片

定义

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

不需要在定义时区分是否是异步函数(这点是针对Python3.5引入的async def定义时说明自己是一个协程)

调度器在合适的点进行切换(非抢占式的,但切换点也不是任意的点,传统是需要显示写出来,goroutine不需要)

可能切换的点:I/O,select  ; channel ;等待锁;函数调用(有时);runtime.Gosched()

注意:以上只是参考,不能保证切换,不能保证在其他地方不切换

使用-race来检测数据访问冲突

 

 

代码

goroutine.go

package main

import (
	"fmt"
	"time"
)
//注意:两个i都是i没关系的  其余语言10/100个并发执行可以,但是1000个就很难啦
func main() {
	for i := 0; i < 1000; i++ {
		go func(i int) {  //开goroutine  这里写成一个匿名函数要方便点  
			for {
				fmt.Printf("Hello from goroutine %d
", i) //Printf是一个io操作 由协程之间切换
			}
		}(i)
	}
	time.Sleep(time.Minute)//如果没有这句话 是没有输出的 因为开了1000个goroutine还没来得及输出就完了  
}  

查看系统究竟起了多少个线程?
top命令查看:CPU 占用率 #TH线程(根据系统核来)

Coroutine协程

子程序是协程的一个特例

协程特点:

轻量级”线程”

非抢占式多任务处理,由协程主动交出控制权 

编译器/解释器/虚拟机层面的多任务

多个协程可在一个或多个线程在工作

func main() {
    var a [10]int
   for i := 0; i<10 ; i++ {
      go func(i int) { //没有i race condition
        for{
          a[i]++ //每个人都不断的去做加法 没有协程之间切换 没办法交出控制权
runtime.Gosched() //手动交出控制权 一般很少用 如果没有这句,该例子程序会陷入死循环
        }
      }(i) //没有i 会报错 index out of range
  }
  time.Sleep(time.Millisecond)
  fmt.Println(a)
}  

普通函数与协程对比:doWork做完了才把控制权交给main

技术分享图片

其他语言对协程支持

Go语言原生支持

C++:通过Boost.Coroutine库支持

Java:不支持 (并不是完全不支持,有第三方的)

Python中:Python3.5以前使用yield关键字实现协程,Python3.5加入了async def 对协程原生支持

 

 

 

以上是关于Go goroutine的主要内容,如果未能解决你的问题,请参考以下文章

go语言--goroutine

Go并发编程--正确使用goroutine

go语言之行--golang核武器goroutine调度原理channel详解

GO语言goroutine

GO语言goroutine

Go语言入门goroutine和channel