Go 内存模型发生在之前(具有共享状态的通道)
Go Memory Model Happens Before (Channels with Shared State)
我正在尝试更全面地了解通道和其他共享状态之间发生之前关系的性质。具体来说,我想看看是否在通道发送和接收操作上创建了某种内存栅栏。
例如,如果我在频道上发送一条消息,则执行围绕修改共享状态 "happen before" send/receive 操作的所有其他操作。在我的特定示例中,我只从单个 go 例程中编写,然后从单个 go 例程中读取。
(旁白:下面示例中的明显答案是将 Person
结构的实例直接放在通道上,但这不是我要问的。)
package main
func main() {
channel := make(chan int, 128)
go func() {
person := &sharedState[0]
person.Name = "Hello, World!"
channel <- 0
}()
index := <-channel
person := sharedState[index]
if person.Name != "Hello, World!" {
// unintended race condition
}
}
type Person struct{ Name string }
var sharedState = make([]Person, 1024)
内存模型保证当通道写操作执行时,在通道操作之前的那个goroutine中的所有操作都是可见的。所以在你的例子中, "unintended race condition" 不会发生,因为当通道被读取时,goroutine 中发生的分配是可见的。当然,这假设没有另一个 goroutine 正在写入同一个变量。如果有另一个 goroutine 写入同一个变量,那么您还需要同步该 goroutine 以避免竞争。
我正在尝试更全面地了解通道和其他共享状态之间发生之前关系的性质。具体来说,我想看看是否在通道发送和接收操作上创建了某种内存栅栏。
例如,如果我在频道上发送一条消息,则执行围绕修改共享状态 "happen before" send/receive 操作的所有其他操作。在我的特定示例中,我只从单个 go 例程中编写,然后从单个 go 例程中读取。
(旁白:下面示例中的明显答案是将 Person
结构的实例直接放在通道上,但这不是我要问的。)
package main
func main() {
channel := make(chan int, 128)
go func() {
person := &sharedState[0]
person.Name = "Hello, World!"
channel <- 0
}()
index := <-channel
person := sharedState[index]
if person.Name != "Hello, World!" {
// unintended race condition
}
}
type Person struct{ Name string }
var sharedState = make([]Person, 1024)
内存模型保证当通道写操作执行时,在通道操作之前的那个goroutine中的所有操作都是可见的。所以在你的例子中, "unintended race condition" 不会发生,因为当通道被读取时,goroutine 中发生的分配是可见的。当然,这假设没有另一个 goroutine 正在写入同一个变量。如果有另一个 goroutine 写入同一个变量,那么您还需要同步该 goroutine 以避免竞争。