Can Go例程可以共享频道的所有权吗?

时间:2014-05-09 19:59:43

标签: concurrency go race-condition channel goroutine

我理解通常,如果我希望从Go例程访问范围外的变量,我有责任创建一个由Go例程在概念上拥有的副本。这对渠道也是如此,还是免除?

Effective Go #channels用“写req := req可能看起来很奇怪,但在Go中执行此操作是合法且惯用的,”这个代码示例:

var sem = make(chan int, MaxOutstanding)
// (other code, filling sem, defining process(..), etc., omitted)

func Serve(queue chan *Request) {
    for req := range queue {
        <-sem
        req := req // Create new instance of req for the goroutine.
        go func() {
            process(req)
            sem <- 1
        }()
    }
}

我碰巧在我自己的项目中几乎复制了这个示例代码(除了我使用chan struct{}而不是chan int作为我的信号量,并将其声明为{{1}的本地代码} func)。盯着它,我想知道是否从多个并发goroutine访问相同的通道真的很好,或者是否需要Serve之类的东西。

2 个答案:

答案 0 :(得分:5)

频道访问是线程安全的,因此您无需锁定它或制作它的本地副本或类似的东西。

答案 1 :(得分:4)

是的,使用多个goroutine中的相同频道没有问题,这样做很正常。

req := req的原因不是为了goroutine的好处,而是需要防止闭包内的意外行为。没有它,循环的每次迭代都会改变闭包内的req值,而不是每次都给它一个唯一的值。

可以在此处找到此效果的简单示例:http://play.golang.org/p/ylRQkh2SeC