33|并发:小channel中蕴含大智慧
该思维导图由 AI 生成,仅供参考
作为一等公民的 channel
- 深入了解
- 翻译
- 解释
- 总结
Go语言中的channel是并发编程中的重要组成部分,基于CSP理论,作为一等公民,可以像普通变量一样使用。channel分为无缓冲和带缓冲两种类型,它们在发送和接收操作上有不同的特性。无缓冲channel的发送和接收操作是同步的,需要放在不同的Goroutine中进行,否则会导致死锁。而带缓冲channel的发送和接收操作是异步的,只有在缓冲区满或空时才会阻塞。文章还介绍了channel的性能测试结果,表明带缓冲channel在数据收发的性能上要明显好于无缓冲channel。此外,还介绍了channel的另外两种用法:用作消息队列和用作计数信号量。通过示例展示了如何在实际应用中使用channel进行Goroutine间的通信和同步。文章还介绍了len(channel)的应用,nil channel的妙用以及与select结合使用的一些惯用法。总的来说,本文通过详细的语法介绍和示例说明,帮助读者快速了解了Go并发中channel的基本概念和使用方法,以及其在并发编程中的重要作用。文章还介绍了channel的另外两种用法:利用default分支避免阻塞、实现超时机制和实现心跳机制。这些用法丰富了channel的应用模式,为读者提供了更多实用的并发编程技巧。
《Tony Bai · Go 语言第一课》,新⼈⾸单¥59
全部留言(46)
- 最新
- 精选
- peison请问计数信号量的例子中,因为jobs的容量是10,这里执行的循环不会导致阻塞,close(jobs) 应该会被执行到,那么下面的for range为什么不会终止,而可以继续运行? go func() { for i := 0; i < 8; i++ { jobs <- (i + 1) } close(jobs) }()
作者回复: 好问题! channel内部数据是排队的,即便被close,依然可以从closed channel中读取到尚未被消费的元素,直到没有可读的元素为止,才真正会变成closed状态。没数据后,如果再读就会得到元素类型的零值了, 对于没数据且closed状态的channel,for range会终止。
2022-04-15623 - 张申傲这节课信息量有点大,需要多看几遍好好消化。请问老师一个问题:如果程序中没有手动 close channel,那么 channel 会在什么时候关闭呢?是否需要借助 defer 去释放 channel 资源呢?
作者回复: channel一旦没有人引用了,就会被gc掉,不关闭也ok。但是如果有goroutine一直在读channel,那么channel一直存在,不会关闭。直到程序退出。
2022-02-2013 - ibin白老师,你好,下面这段可以模拟close(groupSignal) for i := 0;i < 5; i++ { groupSignal<-signal(struct{}{}) } 为什么close(groupSignal) 可以给每个groupSignal都发送了{}
作者回复: close一个channel后,所有阻塞在这个channel接收操作的goroutine都会收到通知,这是Go语言的channel语义就这么定义的。
2022-01-12410 - 木木go的并发原语选择真的是非常精炼:简洁又强大,一个ch就负责了线程通信、同步的多种功能;一个select又实现了对阻塞、非阻塞的控制以及事件循环模式。
作者回复: 👍
2022-03-188 - airmy丶请问下老师: 为什么 "1 对 n 的信号通知机制" 这个例子中,wg.Wait() 一定需要新起一个协程执行呢?而且在本地测试确实只能在新的协程中执行才不会报错,否则会报出: goroutine x [chan receive] 这样的错误。
作者回复: Wait方法的语义就是等待例子中for循环创建的所有子goroutine,直到每个子goroutine都调用完wg.Done才返回。如果不再一个新goroutine执行,wg.Wait就会阻塞住main goroutine,这也将导致后续所有goroutine都阻塞住,然后go运行时检测到所有goroutine都阻塞住了,于是报错退出。
2022-05-1826 - 瓜牛为啥有时需要手动调用close关闭channel,有时又不需要?
作者回复: 首先明确一点:channel如果不close,也不会存在资源泄露的问题。 是否需要close channel完全看需要。 至于如何知道何时需要,看文中对close channel的语义的描述,以及如何基于这种语义的一些妙用。
2022-04-2025 - Unknown element老师我看makechan的源码发现分配内存的时候分了3种情况: 1. 缓冲区大小=0 2. 元素类型不是指针 3. 元素类型包含指针 我想问下为什么2和3要分成两种情况呢?我看区别好像是调用 mallocgc 时第二个参数不一样,但是mallocgc 的源码我就看不懂了。。。希望老师可以简单解释下 谢谢老师~
作者回复: 如果channel中的元素大小为0,那就不需要额外分配缓存(buf); 如果元素类型中不含有指针,那么buf就和hchan一起分配(将来也和hchan一起释放),减少一次heap mem分配。GC只扫描hchan就ok了。 如果元素类型包含指针,那么hchan和hchan.buf单独分配内存,GC分别扫描hchan和buf中的元素。
2022-11-20归属地:北京4 - 每天晒白牙感觉只发送channel和只接收channel类型定义符号,交换一下更好理解,也更形象吧 make(chan<- int, 1) 这个代表只接收 make(<-chan int, 1) 这个代表只发送
作者回复: 由于箭头都是向左的,即<-,所以我区分只发送和只接收型的channel的tip是以 chan这个关键字为中心,将chan关键字看成一个“管子”。当<-在chan的右边,即chan <- 好似向管子里写,这样就是只发送型。当<-在chan的左边,即<- chan ,好似从管子里取,这样就是只接收型。
2022-07-2024 - 罗杰这节课比较绕,要静下心好好学习
作者回复: 👍
2022-01-124 - 怎么睡才能做这种梦另外,select 语句中,如果有多个 case 同时都没有阻塞的话,会随机选择一个 case
作者回复: 👍
2023-03-06归属地:湖北3