type Stat struct {
counters map[string]*int64
countersLock sync.RWMutex
averages map[string]*int64
averagesLock sync.RWMutex
}
它在下面被称为
func (s *Stat) Count(name string) {
s.countersLock.RLock()
counter := s.counters[name]
s.countersLock.RUnlock()
if counter != nil {
atomic.AddInt64(counter, int64(1))
return
}
}
我的理解是,我们首先锁定接收者 s(这是一种 Stat 类型),然后如果计数器确实存在,我们将其添加到它。
问题:
Q1:为什么需要加锁? RWMutex
是什么意思?
Q2: s.countersLock.RLock()
这会锁定整个 receiver s 还是只锁定 Stat 类型的 counters 字段?
Q3: s.countersLock.RLock()
这会锁定平均值字段吗?
Q4:为什么要使用 RWMutex
?我认为通道是 Golang 中处理并发的首选方式?
Q5:这是什么 atomic.AddInt64
。为什么在这种情况下我们需要原子?
Q6:为什么我们要在添加之前解锁?
原文由 samol 发布,翻译遵循 CC BY-SA 4.0 许可协议
RW 代表读/写。 CF 文档:http: //golang.org/pkg/sync/#RWMutex 。
我们需要锁定它以防止其他例程/线程在我们处理它时更改该值。
作为互斥量,只有在调用
RLock()
函数时才会发生锁定。如果任何其他 goroutine 已经调用了WLock()
,那么它会阻塞。您可以在同一个 goroutine 中调用任意数量的RLock()
,它不会锁定。因此它不会锁定任何其他字段,甚至不会锁定
s.counters
。在您的示例中,您锁定地图查找以找到正确的计数器。不,正如 Q2 中所说,a
RLock
只锁定了他自己。Channel 非常有用,但有时不够用,有时又没有意义。
在这里,当您锁定地图访问权限时,互斥量很有意义。对于 chan,您必须有一个缓冲的 1 通道,先发送后接收。不是很直观。
此函数将以原子方式递增给定变量。在你的情况下,你有一个竞争条件:
counter
是一个指针,实际变量可以在释放锁之后和调用之前销毁atomic.AddInt64
。如果您不熟悉这类事情,我建议您坚持使用 Mutexes 并在锁定/解锁之间完成您需要的所有处理。你不应该。
我不知道你想做什么,但这是一个(简单的)例子:https: //play.golang.org/p/cVFPB-05dw