Open geektutu opened 3 years ago
还有一个技巧对于chan只需要做一次信号传递,且没有数据传输可以用 make(chan struct{})
传递时可以用 close
,标准库的 context
就是这么用的。
@zeromake 嗯,没有数据传输推荐使用空结构体 struct{}
,空结构体占用内存为 0。
fmt.Println(unsafe.Sizeof(struct{}{})) // 0
2.3中的第二段用的无缓冲chan,也没使用select发送消息,为什么还能正常退出协程呢
@liron-li 因为主协程超时退出,没有 phase1 的接收方,子协程中 case phase1 <- true:
消息发送失败,返回了。
@geektutu @liron-li 因为主协程超时退出,没有 phase1 的接收方,子协程中
case phase1 <- true:
消息发送失败,返回了。
作者这样回答的话,就和你另一段文字(如下)冲突了: 我们仔细阅读这段代码,其实是非常容易发现问题所在的。done 是一个无缓冲区的 channel,如果没有超时,doBadthing 中会向 done 发送信号,select 中会接收 done 的信号,因此 doBadthing 能够正常退出,子协程也能够正常退出。
但是,当超时发生时,select 接收到 time.After 的超时信号就返回了,done 没有了接收方(receiver),而 doBadthing 在执行 1s 后向 done 发送信号,由于没有接收者且无缓存区,发送者(sender)会一直阻塞,导致协程不能退出。
我的理解是,主协程超时退出,没有phase1的接受方,那么子协程case phase1 <- true仍然是阻塞的,但是可以选择select的default case进行执行,从而避免了协程泄漏问题。
2.1中的做法会不会也导致内存泄漏?因为此时有1000个chan未被close
https://geektutu.com/post/hpg-timeout-goroutine.html
Go 语言/golang 高性能编程,Go 语言进阶教程,Go 语言高性能编程(high performance go)。本文介绍了 Go 语言中实现超时(timeout)退出时常见的错误,即子协程(goroutine)不能正常关闭,导致内存泄漏。常见的实现超时的方式有 time.After 和 context.WithTimeout。