我试图了解 Golang典型的数据竞争之一,其中从多个 goroutine 访问未受保护的全局变量可能会导致竞争条件:
var service map[string]net.Addr
func RegisterService(name string, addr net.Addr) {
service[name] = addr
}
func LookupService(name string) net.Addr {
return service[name]
}
它接着说,我们可以通过使用互斥锁保护它来解决这个问题:
var (
service map[string]net.Addr
serviceMu sync.Mutex
)
func RegisterService(name string, addr net.Addr) {
serviceMu.Lock()
defer serviceMu.Unlock()
service[name] = addr
}
func LookupService(name string) net.Addr {
serviceMu.Lock()
defer serviceMu.Unlock()
return service[name]
}
到目前为止,一切都很好。让我困惑的是:
这个问题的公认答案表明,受 CPU 限制的 goroutine 将使任何其他已被多路复用到同一 OS 线程上的 goroutine 饿死(除非我们明确地使用 yield runtime.Gosched()
)。这是有道理的。
对我来说,上面的RegisterService()
andLookupService()
函数看起来受 CPU 限制,因为没有 IO 也没有产量。这个对吗?
如果是,并且如果GOMAXPROCS 设置为 1,那么上面示例中的互斥锁仍然是绝对必要的吗?goroutine 在可能发生竞争条件的地方受 CPU 限制这一事实是否会解决这个问题?
即使是这样,我认为在现实生活中使用互斥锁仍然是一个好主意,因为我们可能无法保证 GOMAXPROCS 的设置。还有其他原因吗?