Go语言 GMP面试题(GMP调度示例)

GMP面试题

第一段

package main
import "fmt"
import "runtime"
func main() {
	runtime.GOMAXPROCS(1)
	for i :=0; i<10; i++ {
		i := i
		go func() {
			fmt.Println("A:",i)
		}()
	}
	var ch = make(chan int)
	<- ch
}

输出结果
无论执行多少回,A: 9 一定是第一个输出的。后面就让我们来解释一下这是为什么吧。

A: 9
A: 0
A: 1
A: 2
A: 3
A: 4
A: 5
A: 6
A: 7
A: 8

解析
第一句代码: runtime.GOMAXPROCS(1) 设置全局只有一个P表示将goroutine的并行调整至1。同时在只有一个P的时候所有创建的
goroutine都要进入三个队列中(runnext,local,gobal)。

第二句代码: for 开启一个循环10次的代码。

第三句代码: i := i 这里是因为for循环的时候i是一个指针,如果循环内的代码使用for 语句的i,那么所有的goroutine拿到的I都将是9,即i最后一次循环的值。

第四句代码: go func(){} 开启一个goroutine

第五句代码: fmt.Println() goroutine的执行内容是打印A: i

第六句代码: var ch = make(chan int) 创建一个没有缓冲的chan

第七句代码: <- ch 读取一个没有缓冲,如果chan没有信息,则会阻塞,这里用途就是阻塞main()进程

程序执行过程

  • 先将P设置为1,在GMP调度模型中P只有一个的话,所有的goroutine都将进入队列(三个队列)。
  • golang 开一个goroutine的话,都会将goroutine放置在runnext队列,runnext有goroutine的话,会将已有的goroutine放置到local队列中,并将新的goroutine放置到runnext。 即循环开启10个goroutine的话最后一个将在runnext,将会优先执行。这里最后一个goroutine中的i是9,于是9就会最先打印出来
  • 执行完runnext会从local队列的头部开始执行goroutine

第二段

package main
import "time"
import "fmt"
import "runtime"
func main() {
	runtime.GOMAXPROCS(1)
	for i :=0; i<10; i++ {
		i := i
		go func() {
			fmt.Println("A:",i)
		}()
	}
	time.Sleep(time.Hour)
}

1.13 输出结果

A: 0
A: 1
A: 2
A: 3
A: 4
A: 5
A: 6
A: 7
A: 8
A: 9

1.14输出结果

A: 9
A: 0
A: 1
A: 2
A: 3
A: 4
A: 5
A: 6
A: 7
A: 8

解析
第一句代码: runtime.GOMAXPROCS(1) 设置全局只有一个P表示将goroutine的并行调整至1。同时在只有一个P的时候所有创建的
goroutine都要进入三个队列中(runnext,local,gobal)。

第二句代码: for 开启一个循环10次的代码。

第三句代码: i := i 这里是因为for循环的时候i是一个指针,如果循环内的代码使用for 语句的i,那么所有的goroutine拿到的I都将是9,即i最后一次循环的值。

第四句代码: go func(){} 开启一个goroutine

第五句代码: fmt.Println() goroutine的执行内容是打印A: i

第六句代码: time.Sleep(time.Hour) 将程序暂停1小时. 这里注意1.13和1.14的go版本中 time的实现有点不同。 1.13会创建一个goroutine,1.14则不会

程序执行过程

  • 先将P设置为1,在GMP调度模型中P只有一个的话,所有的goroutine都将进入队列(三个队列)。
  • golang 开一个goroutine的话,都会将goroutine放置在runnext队列,runnext有goroutine的话,会将已有的goroutine放置到local队列中,并将新的goroutine放置到runnext。 即循环开启10个goroutine的话最后一个将在runnext,将会优先执行。
  • 此时执行到time.Sleep(time.Hour),在1.13之前 time的实现会另外创建一个goroutine,于是这个goroutine会被最优先执行。之后再从local队列中从开头取。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值