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()-这是锁定整个接收器还是仅锁定Stat类型的counters字段?

Q3:s.countersLock.RLock()-这会锁定平均值字段吗?

问题4:为什么要使用RWMutex?我以为 channel 是处理Golang中并发的首选方式?

Q5:这是什么atomic.AddInt64。为什么在这种情况下我们需要原子的?

问题6:为什么要在添加之前立即解锁?

最佳答案



RW代表读/写。 CF文件:http://golang.org/pkg/sync/#RWMutex

我们需要锁定它,以防止其他例程/线程在处理它时更改该值。



作为互斥锁,仅当您调用RLock()函数时才会发生锁定。如果任何其他goroutine已经调用了WLock(),则它将阻塞。您可以在同一个goroutine中调用任意数量的RLock(),但不会锁定。

因此,它不会锁定任何其他字段,甚至s.counters也不会锁定。在您的示例中,您锁定了 map 查找以找到正确的计数器。



不,正如第二季度所说,RLock仅锁定他自己。



channel 非常有用,但有时不够用,有时没有意义。

在这里,当您锁定 map 访问权限时,互斥锁才有意义。使用chan时,您必须具有1的缓冲chan,然后才发送和接收。不是很直观。



此函数将以原子方式递增给定变量。在您的情况下,您有一个竞争条件:counter是一个指针,并且在释放锁之后和调用atomic.AddInt64之前可以破坏实际变量。
如果您不熟悉这种事情,我建议您坚持使用互斥锁,并在锁定/解锁之间进行所有需要的处理。



不应该。

我不知道您要做什么,但这是一个(简单的)示例:https://play.golang.org/p/cVFPB-05dw

关于go - 如何在Golang中使用RWMutex?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19148809/

10-12 22:23