Состояние гонки возникает, когда две или более операций должны выполняться в правильном порядке, но они этого не делают из-за способа написания программы.
гонка данных: одна параллельная операцияпытается прочитать переменную, в то время как в какое-то неопределенное время другая параллельная операция пытается записать в эту же переменную.
В этом простом примере есть гонка данных, так как мы читаем a
и печатаем, куда идут другие-программа пытается обновить значение.
package main
import "fmt"
func main() {
var a int
go func() {
a++
}()
if a == 0 {
fmt.Println("data:", a)
}
}
возможности вывода:
a
равно 1
, и оно печатается (a
равно 0
, при вводе блока if, но к моменту его печати он изменился.) a
равен 0
, и он печатается (обновление еще не произошло) - ничегонапечатано, (
a
обновлено)
Возвращаясь к вашему вопросу:
1. что может пойти не так с этим условием гонки?
Ответ:
- вывод
a
не определенd, это может быть 2
или 9
. (если ваш первый go func()
запускается первым, a будет 9
, если второй func()
запускается первым, a
будет 2
). - ваше обновление
a
в секунду func()
, теперь сначала func()
запускается и пытается обновить, функция, которая записала в последнюю очередь a
, определит вывод. Это может быть 2
или 9
еще раз. - блокировки используются в предположении, что в любое время только одна подпрограмма удерживает ее, и когда у нее есть доступ, никакая другая переменная не записывает в нее, потому что они не получают эксклюзивную блокировку, но если они естьОбщая переменная не защищена блокировкой, поэтому она может обращаться к переменной и вносить необходимые изменения.
2. Почему сейчас у нас нет предупреждения о состоянии гонки?
Ответ:
Потому что теперь в любой момент времени только одна программа может получить доступ к a
и обновить его.Но даже сейчас a
не является детерминированным, который когда-либо func()
запускается последним, определит это.(даже в этом состоянии гонки можно преодолеть это с помощью правильной синхронизации).
-race
не может определить этот тип условий race
, потому что это почти невозможно сделать.