比赛条件。不知道为什么
Race condition. Cannot figure out why
当我 运行 我的代码时,出现了竞争条件。它是并发安全存储的简单实现。当我将 get() 方法中的接收器更改为 (p *storageType)
时,竞争条件消失了。我很困惑。我需要有人可以向我解释这种行为。
package main
type storageType struct {
fc chan func()
value int
}
func newStorage() *storageType {
p := storageType{
fc: make(chan func()),
}
go p.run()
return &p
}
func (p storageType) run() {
for {
(<-p.fc)()
}
}
func (p *storageType) set(s int) {
p.fc <- func() {
p.value = s
}
}
func (p storageType) get() int {
res := make(chan int)
p.fc <- func() {
res <- p.value
}
return <-res
}
func main() {
storage := newStorage()
for i := 0; i < 1000; i++ {
go storage.set(i)
go storage.get()
}
}
在 main()
中,storage
变量的类型为 *storageType
。如果 storageType.Get()
有值接收者,那么 storage.get()
意味着 (*storage).get()
.
get()
调用将 storageType
作为接收者,因此必须取消引用 storage
指针变量以制作副本(将用作接收者值)。此复制意味着必须读取指向的 storageType
结构的值。但是此读取与读取和写入结构(其 value
字段)的 run()
方法不同步。
如果你把get()
的接收者改成一个指针(类型*storageType
),那么接收者又会是一个副本,但这次是指针的副本,而不是尖头结构。因此不会发生结构的非同步读取。
查看可能的重复项:
第一个:您的 main
函数不会等待所有 goroutine 完成。当 main
时,所有 goroutines 都被强制 return。
考虑使用 sync.WaitGroup
当我 运行 我的代码时,出现了竞争条件。它是并发安全存储的简单实现。当我将 get() 方法中的接收器更改为 (p *storageType)
时,竞争条件消失了。我很困惑。我需要有人可以向我解释这种行为。
package main
type storageType struct {
fc chan func()
value int
}
func newStorage() *storageType {
p := storageType{
fc: make(chan func()),
}
go p.run()
return &p
}
func (p storageType) run() {
for {
(<-p.fc)()
}
}
func (p *storageType) set(s int) {
p.fc <- func() {
p.value = s
}
}
func (p storageType) get() int {
res := make(chan int)
p.fc <- func() {
res <- p.value
}
return <-res
}
func main() {
storage := newStorage()
for i := 0; i < 1000; i++ {
go storage.set(i)
go storage.get()
}
}
在 main()
中,storage
变量的类型为 *storageType
。如果 storageType.Get()
有值接收者,那么 storage.get()
意味着 (*storage).get()
.
get()
调用将 storageType
作为接收者,因此必须取消引用 storage
指针变量以制作副本(将用作接收者值)。此复制意味着必须读取指向的 storageType
结构的值。但是此读取与读取和写入结构(其 value
字段)的 run()
方法不同步。
如果你把get()
的接收者改成一个指针(类型*storageType
),那么接收者又会是一个副本,但这次是指针的副本,而不是尖头结构。因此不会发生结构的非同步读取。
查看可能的重复项:
第一个:您的 main
函数不会等待所有 goroutine 完成。当 main
时,所有 goroutines 都被强制 return。
考虑使用 sync.WaitGroup