Why does the following program hang when the time.Sleep(time.Nanosecond)
is commented out?
package main
import "fmt"
import "time"
import "sync/atomic"
func main() {
var ops uint64 = 0
for i := 0; i < 50; i++ {
go func() {
for {
atomic.AddUint64(&ops, 1)
time.Sleep(time.Nanosecond)
}
}()
}
time.Sleep(time.Millisecond)
opsFinal := atomic.LoadUint64(&ops)
fmt.Println("ops:", opsFinal)
}
Second question, why does running this program in the sandbox result in "process took too long"?
It's because goroutine is cooperative (not fully preemptive) task, and the context switch only happen when there's some IO, system call, time.Sleep()
, or calling large function which have to extend the stack.
Reference:
Your atomic.AddUint64(&ops, 1)
is small function which does not have to extend stack. so the context switch never occurs.
Since main thread is also a goroutine, it does not acquire context switch, and sleeps forever.
There's an open issue to make golang preemptive in tight loop, but not yet solved.
More useful references: