Go协程能够共享对通道的所有权吗?

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

Can Go routines share ownership of a channel?

问题

我理解通常情况下,如果我希望从Go协程中访问一个超出作用域的变量,那么我有责任创建一个副本,以便概念上由Go协程拥有。对于通道是否也适用这一规则呢?

Effective Go #channels 用这样的话解释了这个问题:“写req := req可能看起来很奇怪,但在Go语言中这是合法且惯用的”,并提到了以下代码示例:

var sem = make(chan int, MaxOutstanding)
// (其他代码,填充sem,定义process(..)等,被省略)

func Serve(queue chan *Request) {
    for req := range queue {
        <-sem
        req := req // 为协程创建req的新实例。
        go func() {
            process(req)
            sem <- 1
        }()
    }
}

我碰巧在自己的项目中几乎复制了这个示例代码(除了我使用chan struct{}而不是chan int作为信号量,并将其声明为Serve函数的局部变量)。仔细观察后,我想知道是否可以从多个并发的Go协程中访问同一个通道,或者是否需要像sem := sem这样的操作。

英文:

I understand that usually, if I wish to access an out-of-scope variable from a Go routine, it is my responsibility to create a copy to be conceptually owned by the Go routine. Is this also true for channels, or are those exempt?

Effective Go #channels explains this with the words "it may seem odd to write req := req but it's a [sic] legal and idiomatic in Go to do this," referring to this code example:

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

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

I happened to have very nearly replicated this example code in my own project (except that I am using a chan struct{} rather than chan int for my semaphore, and declare it local to the Serve func). Staring at it, I am wondering if accessing the same channel from multiple concurrent goroutines is really fine, or if something like sem := sem is called for.

答案1

得分: 5

是的,使用多个goroutine从同一个通道接收数据没有问题,这是很正常的做法。

req := req 的目的不是为了goroutine的好处,而是为了防止闭包中出现意外行为而必需的。如果没有它,循环的每次迭代都会改变闭包中的req的值,而不是为其赋予每次迭代一个唯一的值。

可以在这里找到一个快速示例:http://play.golang.org/p/ylRQkh2SeC

英文:

Yes, there is no issue with using the same channel from multiple goroutines, it's quite normal to do so.

The reason for the req := req is not for the benefit of the goroutine, but is instead required to prevent unexpected behavior within the closure. Without it, each iteration of the loop will change the value of req within the closure rather than giving it a unique value each time.

A quick example of this effect can be found here: http://play.golang.org/p/ylRQkh2SeC

答案2

得分: 4

通道访问是线程安全的,因此您不需要对其进行锁定、制作本地副本或其他任何操作。

英文:

Channel accesses are thread-safe, so you do not need to lock it or make local copies of it or anything like that.

huangapple
  • 本文由 发表于 2014年5月10日 03:59:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/23572990.html
匿名

发表评论

匿名网友

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

确定