为什么我的for循环仅在我放慢速度时才起作用?

This code prints 0, but if I insert time.Sleep(0) into the updater loop, it prints >1

var Nonce int = 0

func Updater(){
    for{
        Nonce += 1
    }
}

func main(){
    go Updater()
    time.Sleep(time.Second)
    fmt.Printf("%d
",Nonce)
}

Your main function spins up a goroutine to run Updater and then immediately exits. Without the sleep, Updater doesn't have time to start and do its thing. This code is racy - it will sometimes work as you expect and sometimes won't. You have to synchronize the Updater goroutine with main somehow, using a channel or a wait group for example.

Moreover, you're updating the Nonce global in one goroutine and reading it in another - this is a data race. You'll need to synchronize access to this var with a mutex.


Here's a more correct variant of your code, though it's still rather non-sensical (why do you need a goroutine to run the busy loop?)

package main

import (
    "fmt"
    "sync"
)

var Nonce int = 0

func Updater(wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 1000; i++ {
        Nonce += 1
    }
}

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    go Updater(&wg)
    wg.Wait()
    fmt.Printf("%d
", Nonce)
}

Here we use a WaitGroup for the Updater to signal "I'm done" to the main goroutine, which only then checks the value of Nonce. This program should print "1000" every time

nonce.go:

package main

import (
  "fmt"
  "time"
)

var Nonce int = 0

func Updater() {
  for {
      Nonce += 1
  }
}

func main() {
  go Updater()
  time.Sleep(time.Second)
  fmt.Printf("%d
", Nonce)
}

First, the Go gc compiler is an optimizing compiler. There is no synchronization between the goroutines. Therefore the Nonce += 1 statement is elided, and the value of Nonce stays at zero. See the compiled code:

$ go build nonce.go
$ objdump -d -S ./nonce

Output:

var Nonce int = 0

func Updater() {
    for {
        Nonce += 1
  4888f0:   eb fe                   jmp    4888f0 <main.Updater>
  4888f2:   cc                      int3   
    }
}

Second, if we run the Go data race detector, some optimization is suppressed. Therefore,a data race condition is detected for the Nonce variable. The results of a data race are undefined.

$ go run -race nonce.go
==================
WARNING: DATA RACE
Read at 0x0000005f2648 by main goroutine:
  main.main()
      /home/peter/gopath/src/nonce.go:19 +0x63

Previous write at 0x0000005f2648 by goroutine 6:
  main.Updater()
      /home/peter/gopath/src/nonce.go:12 +0x56

Goroutine 6 (running) created at:
  main.main()
      /home/peter/gopath/src/nonce.go:17 +0x46
==================
42758109
Found 1 data race(s)
exit status 66
$