Причина, по которой результат не совпадает, заключается в том, что time.Sleep(time.Second)
не гарантирует, что все ваши процедуры будут выполнены за промежуток времени в одну секунду. Даже если вы выполните go run main.go
, это не гарантирует, что вы будете получать один и тот же результат каждый раз. Вы можете проверить это, если вместо time.Second
поставить time.Milisecond
, вы увидите гораздо более противоречивые результаты.
Какое бы значение вы ни указали в методе time.Sleep
, это не гарантирует выполнения всех ваших подпрограмм, это просто означает, что менее вероятно, что все ваши подпрограммы не завершатся вовремя.
Для получения стабильных результатов вы захотите немного синхронизировать ваши программы. Вы можете использовать WaitGroup
или каналы.
С WaitGroup
:
//rest of the code above is the same
func main() {
counter := atomicCounter{}
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func(no int) {
for i := 0; i < 10000; i++ {
counter.Add(1)
}
wg.Done()
}(i)
}
wg.Wait()
fmt.Println(counter.Value())
}
С каналами:
func main() {
valStream := make(chan int)
doneStream := make(chan int)
result := 0
for i := 0; i < 100; i++ {
go func() {
for i := 0; i < 10000; i++ {
valStream <- 1
}
doneStream <- 1
}()
}
go func() {
counter := 0
for count := range doneStream {
counter += count
if counter == 100 {
close(doneStream)
}
}
close(valStream)
}()
for val := range valStream {
result += val
}
fmt.Println(result)
}