Acesso simultâneo a mapas com 'range' no Go
O "Ir mapas em ação"nos estados do blog Go:
Os mapas não são seguros para uso simultâneo: não está definido o que acontece quando você os lê e escreve simultaneamente. Se você precisar ler e gravar em um mapa a partir de goroutines em execução simultânea, os acessos deverão ser mediados por algum tipo de mecanismo de sincronização. Uma maneira comum de proteger mapas é com o sync.RWMutex.
No entanto, uma maneira comum de acessar mapas é iterar sobre eles com orange
palavra-chave Não está claro se, para fins de acesso simultâneo, a execução dentro de umrange
loop é uma "leitura" ou apenas a fase "turnover" desse loop. Por exemplo, o código a seguir pode ou não entrar em conflito com a regra "sem concorrentes simultâneos em mapas", dependendo da semântica / implementação específica dorange
Operação:
var testMap map[int]int
testMapLock := make(chan bool, 1)
testMapLock <- true
testMapSequence := 0
...
func WriteTestMap(k, v int) {
<-testMapLock
testMap[k] = v
testMapSequence++
testMapLock<-true
}
func IterateMapKeys(iteratorChannel chan int) error {
<-testMapLock
defer func() {
testMapLock <- true
}
mySeq := testMapSequence
for k, _ := range testMap {
testMapLock <- true
iteratorChannel <- k
<-testMapLock
if mySeq != testMapSequence {
close(iteratorChannel)
return errors.New("concurrent modification")
}
}
return nil
}
A ideia aqui é que orange
"iterador" é aberto quando a segunda função está aguardando um consumidor receber o próximo valor e o gravador não é bloqueado no momento. Entretanto, nunca é o caso de duas leituras em um iterador único nos dois lados de uma gravação - este é um iterador "fail fast", que empresta um termo Java.
Existe algo em algum lugar na especificação do idioma ou em outros documentos que indique se isso é algo legítimo a ser feito? Eu pude ver isso de qualquer maneira, e o documento citado acima não está claro sobre exatamente o que constitui uma "leitura". A documentação parece totalmente silenciosa sobre os aspectos de simultaneidade dofor
/range
declaração.
(Observe que esta pergunta é sobre a moeda defor/range
, mas não uma duplicata de:Acesso simultâneo ao mapa Golang com alcance - o caso de uso é completamente diferente e estou perguntando sobre o requisito de bloqueio preciso na palavra-chave 'range' aqui!)