Go-chan并发
Channel是Go中的一个核心类型,可以把它看作一个管道,通过它可以完成goroutine之间的通信。Channel是FIFO的队列,而且当多个goroutine可以同时读写channel而不用考虑同步。
基本操作——箭头表示着数据的方向
1 | ch := make(chan int)//通过make函数创建一个可读可写Int类型的channel-v |
Channel的类型——只读只写 读写同时###
1 | chan T //可以接收和发送类型为T的数据 |
Channel的创建和关闭
1 | ch := make(chan int , 100)//创建一个100容量的channel,当channel空的时候,receiver队列阻塞,当channel满的时候,sender队列阻塞。如果没有设置大小,就默认设置为0 |
这句语句可以检查channel的开关状态,如果ok为false表示着 channel已经被关闭了
- 如果向一个已经关闭的channel写数据会抛出运行时异常
- 如果读取一个已经关闭的channel,则会将缓冲区的数据读取完,而且可以一直读取该channel数据类型的零值t
- 往一个nil channel中读写数据都会被Block
###Select——适用于管道的Switch
1 | func main() { |
select是Go中的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接收。select随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case为止。
- 每个case都必须是一个通信
- 所有channel表达式都会被求值
- 所有被发送的表达式都会被求值
- 如果任意某个通信可以进行,它就执行;其他被忽略。
- 如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。 如果没有default字句,select将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。
timeout>
select有很重要的一个应用就是超时处理。因为select语句当没有case可处理时会无限等待。因此需要一个超时操作来处理。
1 | func main() { |
Timer/Ticker
定义了一个Timer后,会阻塞规定的时间,然后输出一个channel,在将来的那个时间Channel提供了一个当前时间值。
1 | timer := time.NewTimer(time.Second*2) |
倘若只是想阻塞线程一定时间,使用time.sleep即可。
可以使用timer.stop来停止计时器
1 | timer2 := time.NewTimer(time.Second) |
Ticker是一个定时器,会不断的以设定的时间为间隔Interval
1 | func main() { |
使用channel实现同步###
1 | ch := make(chan bool, 1) |