给出以下示例:http://play.golang.org/p/owvJ8Oi77S
func produce(dataChannel chan int) {
for i := 0; i < 10; i++ {
dataChannel <- i
}
}
func main() {
dataChannel := make(chan int)
go produce(dataChannel)
go produce(dataChannel)
go produce(dataChannel)
for i := 0; i < 30; i++ {
data := <-dataChannel
fmt.Printf("%v ", data)
}
}
我的假设是从多个go例程中写入一个不安全的通道正确吗?
是否有一种通用/惯用的方法可以安全地执行此操作?我知道你可以为每个生成数据的例程创建一个单独的通道,我只是想知道这是否是最干净的解决方案还是有其他替代方案。
答案 0 :(得分:30)
频道完全是线程安全的。它们是goroutines之间进行通信的官方方式。我认为您的代码没有任何问题。这就是Go的美丽。
答案 1 :(得分:5)
通道旨在在线程之间共享(这是“线程安全”的正常含义)。使用频道意味着您没有共享内存,您可能会面临种族危险。所以丹尼尔的答案是正确的:使用渠道,因为这就是他们的目的。
但请注意,如果存在设计错误,goroutines会创建通信顺序进程的网络,有时会死锁。他们也可以活锁(同样的事情,但忙碌)。
关于如何避免死锁/活锁,有相当多的知识。其中很大一部分来自奥卡姆在80年代和90年代流行的日子。杰里米·马丁(Design Strategy for Deadlock-Free Concurrent Systems),彼得·韦尔奇(Higher Level Paradigms)和其他人都有一些特殊的宝石。