Я столкнулся с проблемой синхронизации при использовании goroutines. Моя программа выводит непредсказуемые результаты. Я проверил документ, а для небуферизованных каналов нет возможности проверить, были ли обработаны все сообщения. Я упростил проблему к этому маленькому демо-коду, который все еще демонстрирует проблему. Ясно, что это не проблема с Golang, а с моим кодом. Очевидно, что я не использую правильный шаблон параллелизма.проблема синхронизации параллелизма golang
Вопрос в том, как это решить. Если возможно, я не хотел бы закрывать канал и не останавливать улей. Думаю, было бы здорово, если бы я мог предположить, что, как только все пчелиные курорты закончатся, этот улей уже сделан (это то, что я пробовал с помощью wg.Wait()).
package main
import(
"fmt"
"sync"
"time"
)
func main() {
count := int64(0)
c := make(chan int64)
var wg sync.WaitGroup
// bees
for i:=0; i<5000;i++{
wg.Add(1)
go func(in chan int64) {
defer wg.Done()
time.Sleep(100)
in <- 2
}(c)
}
// hive
go func() {
for out := range c {
count += out
}
}()
wg.Wait()
// bang! but why?
fmt.Println(count)
}
// every now and again the program prints out before it is finished
// $ go run pattern1.go
// 10000
// $ go run pattern1.go
// 9998
// $ go run pattern1.go
// 9998
// $ go run pattern1.go
// 10000
// $ go run pattern1.go
// 10000
// $ go run pattern1.go
// 9998
У вас есть гонки данных в коде, пожалуйста, запустите ваш код с флагом '-race' (go run/build -race). Это будет печатать информацию о гонках данных по мере их появления. – nussjustin
Вы не можете определить, обрабатывал ли цикл «hive» все значения с 'c', не закрывая' c', или вставляя другой счетчик и примитив синхронизации. Если все goroutines сделаны, то в чем смысл не закрывать канал? – JimB
Флаг -race должен быть выполнен после запуска, но перед именем файла. Все, что после имени файла передается вашему процессу, но -race - это флаг компилятора. – nussjustin