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看了好几篇文章,还是不太懂,但还是有一些小小的收获,以后在细细的研究一下!
- G代表goroutine,也叫协程,当我们使用go关键字的时候,就会创建它
- P是一个在G和M直接的中间层。它可以组织管理很多个G跑在一个M上
- M可以看做是一线程
2.2 如果不去看G,P,M里面的细节的话,我的理解就是 执行时,每个M都会绑定一个P,P会管理多个G的在M上的执行。
2.3现在GPM模型有了一个大概的框了,那里面的G是如何执行的呢!
- 当我们使用go关键字的时候,就会创建一个G对象
- 这个G对象会去找空闲的P,并绑定,绑定的同时创建M对象,现在就是M-P-G了
- 如果没有空闲的P,就会加入到某个未满的M对象绑定的p对象的G队列中.
- 这样G对象就像入栈一样一个一个压了进来,执行时就一个一个取了出来,
- 但这里有个疑问,当某个G对象长时间占用M线程,那么后面G对象就会无法执行,那要怎么解决呢?
- 5.1 原来会有一个特殊的内核线程
sysmon
来帮助我们管理和监控, - 5.2 每一个G对象里面都有一个计数器,由它来判断G对象的运行时间,
- 5.3 当运行时间过长时,就会给这个G对象打上一个超时的标签,这时候这个这个G对象就会中断,然后加入G队列的末端,等待下一次执行。
- 5.4 但有的情况是 G对象获得执行权后,再也无法释放了,比如死循环,看下面的代码
- 5.1 原来会有一个特殊的内核线程
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的模型有了大概了解,日后在结合源码在来更进一步的学习!