Я пытаюсь понять один из Golang typical data races, где доступ к незащищенной глобальной переменной из нескольких goroutines может вызвать состояние гонки:гонки данных при GOMAXPROCS = 1
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]
}
Пока что так хорошо. Что меня смущает это:
Принятая ответ this question предполагает, что центральный процессор переплете goroutine будет голодать любой другой goroutines, которые были мультиплексированы на одной и той же ОС нить (если мы явно не выход с runtime.Gosched()
). Это имеет смысл.
Для меня функции RegisterService()
и LookupService()
выше выглядят как ЦП, так как нет ввода-вывода и нет выхода. Это верно?
Если это так, и если GOMAXPROCS установлен в 1, то является ли это мьютексом в приведенном выше примере, по-прежнему строго необходимым? Не заботится ли о том, что goroutines привязаны к процессору в точке, где могут возникать условия гонки?
Даже если это так, я полагаю, что в реальной жизни, используя мьютекс, здесь по-прежнему хорошая идея, поскольку мы не можем гарантировать, что GOMAXPROCS установлен. Есть ли еще другие причины?
Тем фактом, что подпрограммы Go являются ЦП не означает, что есть нет никаких шансов на то, что процесс будет происходить между ними. Мьютекс по-прежнему необходим. – fuz
Спасибо. Таким образом, goroutine, связанный с процессором, может голодать другими гортанами в одном и том же потоке ОС, иначе это может не произойти. Мы не можем гарантировать это в любом случае. Если да, то знаете ли вы, какие факторы определяют, голова ли голова других или нет? –
CPU Bound goroutine используется для голодания других в одном и том же потоке, но Go 1.2 (почти выпущенный) имеет упреждающий планировщик, так что это уже не так. Это была только воплощение детской ИМХО. (В go 1.2 каждый вызов функции является возможностью для упреждения, поэтому, если ваша функция привязки процессора не вызывает другие функции, она будет голодать на других в одном потоке). –