【问题标题】:potential race condition in go languagego语言中的潜在竞争条件
【发布时间】:2017-04-15 09:00:06
【问题描述】:

我不确定为什么下面的代码有竞争条件,有人可以给我提示吗?我认为没有潜在的竞争条件。先感谢您。

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
 }

【问题讨论】:

  • 你为什么认为有一个?

标签: go


【解决方案1】:

c.sum++ 在一个独立于 inc() 方法执行的 goroutine 中。当inc() 方法退出时,defered 将解锁互斥锁,并且很可能发生在错误的时间,从而导致竞争条件。

正如@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 中?

【讨论】:

  • 我不确定我们是否在想同样的事情。在inc unlock之后,read获取锁之前,goroutine可以修改sum吗?
  • 实际的 c.sum++ 发生在 goroutine 中的事实意味着互斥锁没有保护与增量有关的任何内容。
  • 更好的解决方案是使用atomic.AddInt32,因此不需要锁定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多