GO

82 阅读2分钟
  • go的执行是非阻塞的,不会等待
  • go后面函数的返回值会被忽略
  • 调度器不能保证多个goroutine的执行次序
  • 没有父子goroutine的概念,所有goroutine是平等地被调度和执行
  • go程序会单独为main函数创建一个goroutine,遇到其他go关键字时再去创建其他goroutine
  • go没有暴露goroutine id给用户,因此不能在一个goroutine里显示地调用其他goroutine。runtime包提供了一些函数访问和设置goroutine相关信息。如:

runtime包有关goroutine函数

  • GOMAXPROCS(n int) int //获取或设置可以并发执行的goroutine数目,当大于1表示设置GOMAXPROCS的值,否则表示查询。
  • Goexit() 结束当前goroutine的运行,Goexit在结束当前goroutine前会调用goroutine中已经注册的defer。
  • Gosched() 放弃当前调度执行机会,将当前goroutine放到队列等待下次被调度。
  • NumCPU() 返回CPU核心数
  • NumGoroutine() 返回当前程序goroutine数量。

下面分别介绍多个goroutine之间如何通信、同步、协同的。

channel 通道

goroutine是Go语言里的并发执行体,通道主要用来完成goroutine之间数据的通信和同步。

Ps:Go的哲学是“不是要通过共享内存来通信,而是通过通信来共享内存”,这样做的好处是避免了使用共享数据通信时同步锁带来的开销。

通道是有类型的,且分为无缓冲区和带缓冲区的chan。

//声明chan
var ch chan int
//初始化chan
ch = make(chan int)
//初始化带缓冲区的chan
ch = make(chan int, 10)
//声明并初始化chan
ch := make(chan int, 10)

无缓冲区通道
语法:make(chan datatype)

可以通过内置函数len和cap查看通道剩余空间和总容量。无缓冲的len和cap总是0,无缓存通道既可以用于通信也可以用于两个goroutine同步。

func demo2()  {
	//使用无缓冲的通道实现goroutine之间的同步等待
	ch := make(chan int)
	go func() {
		sum := 0
		for i := 0; i<10001; i++{
			sum++
		}
		println(sum)
		ch <- 1
	}()
	<-ch
}

带缓冲区的通道
语法:make(chan datatype, length)

示例:
c :=make(chan int , 1024)
这个例子创建了一个大小1024的int类型的channel,即使没有读取方,写入方也可以一直向channel里写入,直到缓冲区被填满之前都不会阻塞。