go语言中的goroutine和channel
- goroutine的特性
- chan有关
goroutine的特性
- go的执行是非阻塞的,不会等待
- go后面的函数的返回值会被忽略
- 调度器不能保证多个goroutine的执行次序
- 没有父子goroutine的概念,所有的goroutine是平等地被调度和执行的
- Go程序在执行时会单独为main函数创建一个goroutine,遇到其他go关键字时再去创建其他的goroutine
- Go没有暴露goroutine id给用户,所以不能再一个goroutine里面显示地操作另一个goroutine,不过runtime包提供了一些函数和设置goroutine的相关信息
GOMAXPROCS(n int)int
该函数用来设置或查询可以并发执行的goroutine数量,当n>1的时候表示设置数量
Goexit
该函数是结束当前goroutine的运行,Goexit在结束当前goroutine运行之前会调用当前goroutine已经注册的defer。Goexit不会产生panic,所以该goroutine defer里面的recover都返回nil
Gosched
该函数是放弃当前调度执行机会,将当前goroutine放到队列中等待下次被调度。
chan有关
chan是goroutine之间通信和同步的重要组件。
通道分无缓冲的通道和有缓冲的通道,Go提供内置函数len和cap,无缓冲的通道的len和cap都是0,有缓冲的通道的len表示没有被读取的元素数量,cap代表整个通道的容量。
- 无缓冲的通道既可以用于通信,也可以用于两个goroutine的同步,有缓冲的通道主要用于通信。
- goroutine运行结束后退出,写到缓冲通道的数据不会消失,他可以缓冲和适配两个goroutine处理速率不一致的情况,缓冲通道和消息队列类似,有削峰和增大吞吐量的功能。
- panic:
(1)向已经关闭的通道写数据会导致panic,最好是由写入者关闭通道,能最大程度地避免向已经关闭的通道写数据而导致的panic
(2)重复关闭的通道会导致panic - 阻塞
(1)向未初始化的通道写数据或读数据都会导致当前goroutine的永久阻塞
(2)向缓冲区已满的通道写入数据会导致goroutine阻塞
(3)通道中没有数据,读取该通道会导致goroutine阻塞 - 非阻塞
(1)读取已经关闭的通道不会引发阻塞,而是立即返回通道元素类型的零值,可以使用comma,ok语法判断通道是否已经关闭
(2)向有缓冲且没有满的通道读/写不会引发阻塞