2017-04-15 45 views
0

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

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

你为什么认为有一个? – Carcigenicate

回答

6

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

由于@Flimzy建议使用atomic.AddInt32将根本不需要互斥锁。

两个基于互斥方案是要么不是一个够程增加:

func (c *PossiblySafeCounter) inc() { 
    c.mu.Lock(); 
    defer c.mu.Unlock(); 
    c.sum++ 
} 

还是锁定在解锁的够程:

func (c *PossiblySafeCounter) inc() { 
    go func() { 
     c.mu.Lock(); 
     defer c.mu.Unlock(); 
     c.sum++ 
    }() 
} 

但说实话,做任何形式的goroutine在这个例子中没有意义。为什么你需要增加到一个goroutine?

+0

我不确定我们是否在考虑同样的事情。在解锁之后,在读取获取锁之前,可以有goroutine修改总和吗? – vkosyj

+2

在goroutine中实际发生'c.sum ++'这一事实意味着互斥锁不能保护与增量有关的任何事情。 –

+2

更好的解决方案是使用['atomic.AddInt32'](https://golang.org/pkg/sync/atomic/#AddInt32),因此不需要锁定。 – Flimzy