Golang параллелизма записи в переменную - почему этот код работает? - PullRequest
0 голосов
/ 23 мая 2019

Я изучаю проблемы параллелизма на Голанге.Я написал некоторый код:

package main

import (
    "fmt"
    "time"
)

func incr(num *int) {
    *num = *num + 1

}

func main() {
    var a = 0

    for i := 0; i < 50; i++ {
        go incr(&a)
    }

    incr(&a)

    time.Sleep(1 * time.Second)
    fmt.Println(a)
}

Результат этого кода: 51

В этом коде я объявил переменную a, которую я увеличиваю в 50 запущенных программах.То, что я прочитал и не понял, этот код должен потерпеть неудачу, потому что несколько goroutines пишут по одному адресу памяти.В этом случае я должен добавить sync.Mutex блокировку, чтобы исправить это.

Код доступен на детской площадке: https://play.golang.org/p/Tba9pfpxaHY

Не могли бы вы объяснить, что на самом деле происходит в этой программе?

1 Ответ

6 голосов
/ 23 мая 2019

Угадай что?Я запустил ваше приложение и получаю различные результаты: иногда 49, иногда 48, иногда 50 (а иногда 51).

Если вы запускаете свое приложение с включенным детектором гонки (go run -race play.go), он говорит, что у вас есть гонки данных:

==================
WARNING: DATA RACE
Read at 0x00c00009a010 by goroutine 7:
  main.incr()
      /home/icza/gows/src/play/play.go:9 +0x3a

Previous write at 0x00c00009a010 by goroutine 6:
  main.incr()
      /home/icza/gows/src/play/play.go:9 +0x50

Goroutine 7 (running) created at:
  main.main()
      /home/icza/gows/src/play/play.go:17 +0x83

Goroutine 6 (finished) created at:
  main.main()
      /home/icza/gows/src/play/play.go:17 +0x83
==================

Когда у вас есть гонки данных, поведение вашего приложения будет undefined .«Кажется, что иногда работает» также вписывается в «неопределенное» поведение, но неопределенное также означает, что оно может делать что-то еще.

См. Связанные вопросы:

Назначение карты другой картебезопасность в golang?

Безопасно ли читать указатель функции одновременно без блокировки?

golang struct одновременное чтение и запись без блокировкитоже работает нормально?

...