πŸ’¬ Π§Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ data race (Π³ΠΎΠ½ΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ…) Π² контСкстС Go?



πŸ“ŒΠ“ΠΎΠ½ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ… β€” ΠΎΠ΄Π½ΠΈ ΠΈΠ· Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ распространСнных ΠΈ самых слоТных для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ Ρ‚ΠΈΠΏΠΎΠ² ошибок Π² ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½Ρ‹Ρ… систСмах. Π“ΠΎΠ½ΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ… Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚, ΠΊΠΎΠ³Π΄Π° Π΄Π²Π΅ Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½Ρ‹ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΎΠ±Ρ€Π°Ρ‰Π°ΡŽΡ‚ΡΡ ΠΊ ΠΎΠ΄Π½ΠΎΠΉ ΠΈ Ρ‚ΠΎΠΉ ΠΆΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, ΠΈ хотя Π±Ρ‹ ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΉ β€” запись. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ эту ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, Π² Go ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ΡΡ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠΈΡ‚ΠΈΠ²Ρ‹ синхронизации.



πŸ“ŒRace Condition (состояниС Π³ΠΎΠ½ΠΊΠΈ) β€” Π±ΠΎΠ»Π΅Π΅ ΡˆΠΈΡ€ΠΎΠΊΠΎΠ΅ понятиС, Ρ‡Π΅ΠΌ Π³ΠΎΠ½ΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ…. Оно описываСт ΡΠΈΡ‚ΡƒΠ°Ρ†ΠΈΡŽ, ΠΊΠΎΠ³Π΄Π° ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ зависит ΠΎΡ‚ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ порядка выполнСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Π“ΠΎΠ½ΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ… β€” ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π²ΠΈΠ΄ΠΎΠ² состояний Π³ΠΎΠ½ΠΊΠΈ, Π½ΠΎ Π½Π΅ СдинствСнный.



ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π³ΠΎΠ½ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…, которая ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ сбоям ΠΈ ΠΏΠΎΠ²Ρ€Π΅ΠΆΠ΄Π΅Π½ΠΈΡŽ памяти:



func main() {

c := make(chan bool)

m := make(map[string]string)

go func() {

m["1"] = "a" //
ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚Π½Ρ‹ΠΉ доступ

c <- true

}()


m["2"] = "b" // Π’Ρ‚ΠΎΡ€ΠΎΠΉ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚Π½Ρ‹ΠΉ доступ

<-c

for k, v := range m {

fmt.Println(k, v)

}

}




❗️Чтобы ΠΏΠΎΠΌΠΎΡ‡ΡŒ Π΄ΠΈΠ°Π³Π½ΠΎΡΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΈΠ΅ ошибки, Go Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ встроСнный Π΄Π΅Ρ‚Π΅ΠΊΡ‚ΠΎΡ€ Π³ΠΎΠ½ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ…. Для Π΅Π³ΠΎ использования Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Ρ„Π»Π°Π³ -race Π² ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ go:



$ go test -race mypkg

$ go run -race mysrc.go

$ go build -race mycmd

$ go install -race mypkg



πŸ“ŒΠŸΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Π°Ρ окруТСния GORACE устанавливаСт ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ Π΄Π΅Ρ‚Π΅ΠΊΡ‚ΠΎΡ€Π° Π³ΠΎΠ½ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ…, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€:



$ GORACE="log_path=/tmp/race/report Strip_path_prefix=/my/go/sources/" go test -race



πŸ‘‰ ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅