21

给定以下示例: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 例程写入通道不安全的假设是否正确?

有没有一种常见/惯用的方法可以安全地做到这一点?我知道您可以为每个生成数据的例程创建一个单独的通道,我只是想知道这是否是最干净的解决方案,或者是否有其他替代方案。

4

2 回答 2

39

通道是完全线程安全的。它们是 goroutine 之间通信的官方方式。我认为您的代码没有任何问题。这就是围棋之美。

于 2012-12-03T20:04:02.997 回答
8

通道旨在在线程之间共享(这是“线程安全”的正常含义)。使用通道意味着您没有共享内存,您可能会面临竞争风险。所以丹尼尔的回答是正确的:使用渠道,因为这就是它们的用途。

但请注意,goroutine 会创建通信顺序进程的网络,如果出现设计错误,有时可能会死锁。他们也可以活锁(同样的事情,但很忙)。

关于如何避免死锁/活锁,有相当多的知识。其中大部分来自 Occam 在 80 年代和 90 年代流行的日子。Jeremy Martin(无死锁并发系统的设计策略)、Peter Welch(高级范式)等人提供了一些特别的杰作。

于 2012-12-04T20:55:24.013 回答