多个Go协程中传输数据的线程安全方式

huangapple go评论73阅读模式
英文:

Thread-safe way to funnel data from multiple go routines

问题

给定以下示例: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协程向一个通道写入是不安全的,这个假设正确吗?

有没有一种常见/惯用的方法可以安全地实现这个?我知道可以为每个产生数据的协程创建一个单独的通道,我只是想知道这是否是最清晰的解决方案,或者是否还有其他选择。

英文:

Given the following example: http://play.golang.org/p/owvJ8Oi77S

func produce(dataChannel chan int) {
	for i := 0; i &lt; 10; i++ {
		dataChannel &lt;- i
	}
}

func main() {
	dataChannel := make(chan int)

	go produce(dataChannel)
	go produce(dataChannel)
	go produce(dataChannel)

	for i := 0; i &lt; 30; i++ {
		data := &lt;-dataChannel
		fmt.Printf(&quot;%v &quot;, data)
	}
}

Is my assumption that writing to a channel from multiple go routines unsafe correct?

Is there a common/idiomatic way to do this safely? I know you can make a separate channel for each routine that's producing data, I was just wondering if that was the cleanest solution or if there are other alternatives.

答案1

得分: 41

通道是完全线程安全的。它们是在 goroutine 之间进行通信的官方方式。我对你的代码没有任何问题。这就是 Go 的美妙之处。

英文:

Channels are completely thread safe. They are the official way to communicate between goroutines. I see nothing wrong with your code. This is the beauty of Go.

答案2

得分: 9

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

但请注意,goroutine 创建了一组通信的顺序进程网络,如果设计有误,有时可能会发生死锁。它们也可能会发生活锁(与死锁类似,但是一直在忙碌)。

有很多关于如何避免死锁/活锁的知识。其中很多来自于Occam 在80年代和90年代流行的时候。有一些特别有价值的论文,如Jeremy Martin的《无死锁并发系统的设计策略》、Peter Welch的《更高级的范式》等。

英文:

Channels are intended to be shared between threads (and this is the normal meaning of "being thread-safe"). Using channels means you DON'T have shared memory, with the race hazards that you would risk. So Daniel's answer is correct: use channels because that's what they're for.

But note that goroutines create networks of communicating sequential processes that can sometimes deadlock if there's a design mistake. They can also livelock (same thing but being busy).

There is a considerable body of knowledge on how to avoid deadlock/livelock. Much of it is from the days when Occam was popular in the '80s and '90s. There are a few special gems from people such as Jeremy Martin (Design Strategy for Deadlock-Free
Concurrent Systems
), Peter Welch (Higher Level Paradigms) and others.

huangapple
  • 本文由 发表于 2012年12月4日 04:01:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/13690734.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定