Goroutines внутри для l oop возвращает разные значения - PullRequest
0 голосов
/ 27 марта 2020

Я пытаюсь практиковать go подпрограммы. что мне здесь не хватает? этот код вернул мне другой массив результатов.

func goRoutinesSearch(body string, keywords []string) {
     lowerBody := strings.ToLower(body)
     var matched []string
     var wg sync.WaitGroup
     wg.Add(len(keywords))
     for _, word := range keywords {
         go func(w string) {
             defer wg.Done()
             if strings.Contains(lowerBody, w) {
                 matched = append(matched, w)
             }
         }(word)
     }
     wg.Wait()
     fmt.Print(matched)
}

спасибо, ребята

1 Ответ

0 голосов
/ 27 марта 2020
matched = append(matched, w)

Это критическая секция , которая не синхронизирована , что приводит к состоянию гонки. Это не операция атома c. Есть много разных промежуточных элементов в подпрограммах go, которые приведут к разным выходам, и абсолютно непредсказуемы с возможностью потери данных.

Самый простой способ сделать этот поточно-безопасный (безопасный для одновременного выполнения) предназначен для синхронизации доступа к matched с мьютексом :

func goRoutinesSearch(body string, keywords []string) {
     lowerBody := strings.ToLower(body)
     var mutex = &sync.Mutex{}
     var matched []string
     var wg sync.WaitGroup
     wg.Add(len(keywords))
     for _, word := range keywords {
         go func(w string) {
             defer wg.Done()
             if strings.Contains(lowerBody, w) {
                 mutex.Lock()
                 matched = append(matched, w)
                 mutex.Unlock()
             }
         }(word)
     }
     wg.Wait()
     fmt.Print(matched)
}

Мьютекс гарантирует, что только одна подпрограмма go способна * От 1016 * до matched в любой момент времени, поэтому у вас никогда не будет перезаписывающих добавок.


Я думаю, что вы все равно можете иметь разные результаты массива в зависимости от порядка выполнения goroutines, но вы не потеряете данные теперь, когда они синхронизированы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...