英文:
potential race condition in go language
问题
我不确定为什么以下代码存在竞态条件,有人可以给我一个提示吗?我认为没有潜在的竞态条件。提前谢谢。
type PossiblySafeCounter struct {
mu sync.Mutex
sum int
}
func (c *PossiblySafeCounter) inc() {
c.mu.Lock();
defer c.mu.Unlock();
go func() {
c.sum++
}()
}
func (c *PossiblySafeCounter) read() int {
c.mu.Lock();
defer c.mu.Unlock();
return c.sum
}
以下是翻译好的部分。
英文:
I am not sure why the following code has the race condition, can someone give me a hint? I think there is no potential race condition. Thank you in advance.
type PossiblySafeCounter struct {
mu sync.Mutex
sum int
}
func (c *PossiblySafeCounter) inc() {
c.mu.Lock();
defer c.mu.Unlock();
go func() {
c.sum++
}()
}
func (c *PossiblySafeCounter) read() int {
c.mu.Lock();
defer c.mu.Unlock();
return c.sum
}
答案1
得分: 6
c.sum++
在一个独立于 inc()
方法执行的 goroutine 中调度。当 inc()
方法退出时,延迟的互斥锁解锁很可能会在错误的时间发生,导致竞态条件。
如 @Flimzy 建议,使用 atomic.AddInt32
可以完全避免使用互斥锁。
基于互斥锁的两种解决方案要么不在 goroutine 中进行递增操作:
func (c *PossiblySafeCounter) inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.sum++
}
要么在 goroutine 中进行锁定和解锁操作:
func (c *PossiblySafeCounter) inc() {
go func() {
c.mu.Lock()
defer c.mu.Unlock()
c.sum++
}()
}
但是,老实说,在这个例子中使用任何类型的 goroutine 都没有意义。为什么需要在 goroutine 中进行递增操作呢?
英文:
The c.sum++
is in a goroutine that is scheduled independently of the execution of the inc()
method. When the inc()
method exits the defer
ed unlock of the mutex will happen and will very likely happen at the wrong time, leading to a race condition.
As @Flimzy suggests using atomic.AddInt32
would remove the need for a mutex at all.
two mutex based solutions are either to not increment in a goroutine:
func (c *PossiblySafeCounter) inc() {
c.mu.Lock();
defer c.mu.Unlock();
c.sum++
}
or do the locking and unlocking in the goroutine:
func (c *PossiblySafeCounter) inc() {
go func() {
c.mu.Lock();
defer c.mu.Unlock();
c.sum++
}()
}
but honestly, doing any kind of goroutine doesn't make sense in this example. Why do you need the increment to be in a goroutine?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论