简介
channel是golang的一个重要特性,可用于goroutine同步和通信,channel基于共享内存实现,具有FIFO特性。
chan的分类
//read and write
chan
//write only
chan<-
//read only
<-chan
此外还可以分为有缓冲
和无缓冲
chan。
无缓冲chan
无缓冲chan,没有缓冲队列,其读写两端需要同步,否之阻塞。可用于goroutine之间的同步操作。
创建无缓冲chan:
ch := make(chan int)
//or: ch := make(chan int, 0)
var rch <-chan int = ch
var wch chan<- int = ch
带缓冲chan
带缓冲的chan有缓冲队列,chan的生产者和消费者可以异步读写,不过再chan缓冲满时写阻塞,在chan的缓冲为空时读阻塞。
创建带缓冲chan:
ch := make(chan int, 20)
var rch <-chan int = ch
var wch chan<- int = ch
其他
迭代chan
可以使用for-range来迭代chan,chan关闭自动退出循环。
for value := range ch {
//todo...
}
panic
在chan关闭后的读写会产生panic。
屏蔽panic:
val, ok := <-ch
//ok's type is bool
使用ok状态来检查chan是否关闭。
非阻塞
对于无缓冲的chan,只有阻塞读写。
对于有缓冲的chan,可以进行非阻塞读写操作。
首先在缓冲区未满的写,缓冲区未空的读都是非阻塞的。
在缓冲未空的读和缓冲满的写的非阻塞操作
-
使用time.timer来进行定时操作,超时退出。(伪的)
-
使用len和cap对chan进行测试,然后读写。
https://golang.google.cn/pkg/builtin/#len
关于chan的线程安全问题
这里将线程安全定义为多个goroutine同时读写一个chan。
chan的读写是线程安全的。
实现原理
【有待填坑】
https://zhuanlan.zhihu.com/p/62391727
https://my.oschina.net/renhc/blog/2246871