Golang基本用法(七)

go: go关键字的使用,GPM模型

Posted by Hzy on November 17, 2019

go关键字应该是学go到现在,最感兴趣的地方了!

1.我们可以利用go关键字来创建goroutine,goroutine是由Go程序来管理和调度的,然后由Go程序来决定分配到每个CPU,我们可以创建多个goroutine来实现并发操作。

下面来写个例子,用一用go关键字。 我们一边打印玩手机,一边打印说话

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
27
28
package main

import (
	"fmt"
	"time"
)

func Talk(){
	for{
		fmt.Println(time.Now(),"我在说话")
		time.Sleep(time.Second)
	}

}
func PlayPhone(){
	for {
		fmt.Println(time.Now(),"我在玩手机")
		time.Sleep(time.Second)
	}
}


func main(){
	go Talk()
	go PlayPhone()
	time.Sleep(time.Hour) //我们让主程序睡眠一会在结束,让goroutine可以顺利跑下去
}

2.学习时,有一个疑问,就是GOMAXPROCS有什么用,从网上研究了下,总结了一些知识点!

  • go 1.5 版本之前的 GOMAXPROCS 默认是 1
  • go 1.5 版本之后的 GOMAXPROCS 默认是 Num of cpu
  • GOMAXPROCS可以设置GPM模型中P的个数,也就限制了M的个数,而M的个数决定了可以有同时多少个线程来执行G中的队列!

    这里涉及了GO中的GPM模型,又是一个新的知识点!!!

2.1看了好几篇文章,还是不太懂,但还是有一些小小的收获,以后在细细的研究一下!

"GPM模型,从下面知乎链接来的"

  • G代表goroutine,也叫协程,当我们使用go关键字的时候,就会创建它
  • P是一个在G和M直接的中间层。它可以组织管理很多个G跑在一个M上
  • M可以看做是一线程

2.2 如果不去看G,P,M里面的细节的话,我的理解就是 执行时,每个M都会绑定一个P,P会管理多个G的在M上的执行。

2.3现在GPM模型有了一个大概的框了,那里面的G是如何执行的呢!

  1. 当我们使用go关键字的时候,就会创建一个G对象
  2. 这个G对象会去找空闲的P,并绑定,绑定的同时创建M对象,现在就是M-P-G了
  3. 如果没有空闲的P,就会加入到某个未满的M对象绑定的p对象的G队列中.
  4. 这样G对象就像入栈一样一个一个压了进来,执行时就一个一个取了出来,
  5. 但这里有个疑问,当某个G对象长时间占用M线程,那么后面G对象就会无法执行,那要怎么解决呢?
    • 5.1 原来会有一个特殊的内核线程sysmon来帮助我们管理和监控,
    • 5.2 每一个G对象里面都有一个计数器,由它来判断G对象的运行时间,
    • 5.3 当运行时间过长时,就会给这个G对象打上一个超时的标签,这时候这个这个G对象就会中断,然后加入G队列的末端,等待下一次执行。
    • 5.4 但有的情况是 G对象获得执行权后,再也无法释放了,比如死循环,看下面的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import (
	"fmt"
	"runtime"
)


func main() {
	go func() {
		for{}
	}()

	fmt.Println("gogogogo")
	runtime.Gosched()
	runtime.GC()
	fmt.Println("done")
}

总结

现在对go的GPM的模型有了大概了解,日后在结合源码在来更进一步的学习!

参考文章