оператору go ++ нужен мьютекс? - PullRequest
0 голосов
/ 29 января 2019

Оператору go ++ нужен мьютекс?Кажется, что когда я не использую мьютекс, я теряю некоторые данные, но по логике ++ просто добавляю +1 значение к текущему значению, так что даже если порядок неправильный, все равно всего 1000 прогонов должно произойти, нет?Пример:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    i := 0
    for r := 0; r < 1000; r++ {
        wg.Add(1)
        go func() {
            i++
            fmt.Println(i)
            wg.Done()
        }()
    }
    wg.Wait()
    fmt.Printf("%d Done", i)
}

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Чтобы «просто добавить 1 к текущему значению», компьютер должен прочитать текущее значение, добавить 1 и записать новое значение обратно.Ясно, что порядок имеет значение;стандартный пример:

Thread A     Thread B
Read: 5
             Read: 5
+1 = 6
             +1 = 6
Write: 6
             Write: 6

Значение, начинающееся с 5, два потока выполнения добавляются по одному, и в результате получается 6 (когда должно быть 7), потому что чтение B произошло до записи A.

Но здесь есть более важное заблуждение: многие думают, что в случае гонки код будет либо читать старое значение, либо он будет читать новое значение. Это не гарантируется .Это может быть то, что происходит большую часть времени.Это может происходить постоянно на вашем компьютере с текущей версией компилятора и т. Д. Но на самом деле на самом деле возможно для кода, который обращается к данным небезопасным / быстрым способом, чтобы любой результат, даже полный мусор.Нет никакой гарантии, что значение, которое вы читаете из переменной, соответствует любому значению, которое она имела когда-либо , если вы вызвали гонку.

0 голосов
/ 29 января 2019

просто добавьте +1 к текущему значению

Нет, это не "просто добавить".Это

  1. Считать текущее значение
  2. Вычислить новое значение (на основе прочитанного) и записать его

Посмотрите, как это может сломаться с несколькими одновременными действующими лицами?

Если вы хотите атомарные приращения, посмотрите sync / atomic .Примеры: https://gobyexample.com/atomic-counters

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