W swojej odpowiedzi na to pytanie: Golang for Windows erratic behavior? użytkownik @distributed zalecany do blokowania/synchronizowania dostępu do wspólnej zmiennej na równoczesnych goroutines.Jak zablokować/zsynchronizować dostęp do zmiennej w ruchu podczas równoczesnych goroutinów?
Jak mogę to zrobić?
Szerzej na ten temat:
otrzymuję ten kod (wracającą funkcję z zamknięciem na views
) działającym na kilku goroutines w tym samym czasie:
func makeHomeHandler() func(c *http.Conn, r *http.Request) {
views := 1
return func(c *http.Conn, r *http.Request) {
fmt.Fprintf(c, "Counting %s, %d so far.", r.URL.Path[1:], views)
views++
}
}
to wygląda funkcja IO trwa nadszedł czas, iw efekcie uzyskać ten rodzaj wyjścia: sumujący
Counting monkeys, 5 so far.
Counting monkeys, 5 so far.
Counting monkeys, 5 so far.
Counting monkeys, 8 so far.
Counting monkeys, 8 so far.
Counting monkeys, 8 so far.
Counting monkeys, 11 so far.
jest w porządku, ale gdy zostanie wydrukowany widzę, że drukowanie operacja + incr ementowanie w ogóle nie jest atomowe.
Gdybym go zmienić na:
func makeHomeHandler() func(c *http.Conn, r *http.Request) {
views := 0
return func(c *http.Conn, r *http.Request) {
views++
// I can only hope that other goroutine does not increment the counter
// at this point, i.e., right after the previous line and before the
// next one are executed!
views_now := views
fmt.Fprintf(c, "Counting %s, %d so far.", r.URL.Path[1:], views_now)
}
}
Wydaje się działać prawidłowo, ale nie jestem całkowicie pewien, czy to nie zawiedzie w końcu ...
Oprócz odpowiedzi wymieniających 'sync/atomic', przycisk [' pakiet expvar'] (https://golang.org/pkg/expvar/) jest kolejnym rozwiązaniem, jeśli również chcę/potrzebuję * publicznie * wystawiać wartości przez HTTP (np. do wysyłania zapytań do wartości na zdalnie uruchomionym serwerze). –