1、什么是 channel(管道/通道)?
在 golang 中,channel 是多个 goroutine (线程) 之间传递和同步数据的一种手段。同一时刻,仅有一个线程可以向 channel 发送数据,同样的,同一时刻也只能有一个线程能从 channel 读取数据。
channel 的特性使得它可以解决并发编程可能造成的死锁问题,可以作为Mutex(上锁)及sync多线程编程的替代方案,可以简化代码结构。
2、channel 的声明方式
1varc chanint// var 关键字声明,缓冲int类型数据
2 varc chanstring// 缓冲string类型数据
3 c := make(chanint)// make关键字声明,非缓冲管道
4 c := make(chanint,10)// 缓冲管道
5 type ChanInt chanint// 设置别名
总结为:
通过chan关键字标识为管道
有两种声明方式
make方式可以生成缓冲管道及非缓冲管道
3、缓冲 channel 和无缓冲 channel 区别?
1 channel1 := make(chanint)// 无缓冲
2 channel2 := make(chanint,2)// 有缓冲
3 len(channel1)// 长度
4 cap(channel2)// 容量
无缓冲:
缓冲为1,最多只能缓冲1个数据。无缓冲的读写实际为同步操作,只有当写与读操作匹配时,才会继续,否则会死锁!所以不能同时将读写置于主线程,如果主线程中有读/写操作,必须置于分线程的声明后,
非缓冲的读和写操作必须“相遇”才能执行,否则会阻塞。
就是一个送信人去你家门口送信,你不在家他不走,你一定要接下信,他才会走
有缓冲:
最大缓冲等于容量,相当于一个先进先出的队列。有缓冲的管道,只有当管道容量已存满,在未取走值的情况下继续放值时才会发生阻塞。
4、巧用 channel
通过channel的某些奇技淫巧,可以替代sync,简化代码量,如下示例:
1、 在一个非缓冲管道中,依次循环存入值,并逐个取出
sync实现方法:
package main
import(“fmt””sync”)
var wg sync.WaitGroup //队列
func main(){
// 先创建一个非缓冲管道
c := make(chanint)
wg.Add(2)
gofunc(){
//子线程
for i :=0; i <10; i++ {
c <- i//写入数据fmt.Println(“写入数据”) }
wg.Done()
}()
go func (){
fori :=0; i <10; i++ {
a := <-c
fmt.Println(a)
//读取数据fmt.Println(“读取数据”) }
wg.Done()
}()
wg.Wait()}
blockchainb.github.io