Going through Go by Example: Atomic Counters. The code example calls runtime.Gosched
after calling atomic.AddUint64
.
atomic.AddUint64
is called to
Unfortunately, I am finding the explanation not so meaty and satisfying.
I tried running the sample code (comments removed for conciseness):
package main
import "fmt"
import "time"
import "sync/atomic"
import "runtime"
func main() {
var ops uint64 = 0
for i := 0; i < 50; i++ {
go func() {
for {
atomic.AddUint64(&ops, 1)
runtime.Gosched()
}
}()
}
time.Sleep(time.Second)
opsFinal := atomic.LoadUint64(&ops)
fmt.Println("ops:", opsFinal)
}
without the runtime.Gosched()
(go run conc.go
) and the program never exited even when I reduced the loop from 50 to 1.
Question:
What happens under the hood after the call to atomic.AddUint64
that it is necessary to call runtime.Gosched
? And how does runtime.Gosched
fixes this? I did not find any hint to such a thing in sync/atomic
's documentation.