User-level scheduling lets a language runtime or user-space library schedule goroutines or other user-level threads instead of relying directly on the operating-system kernel. It is usually non-preemptive: execution switches at specific points such as I/O or an explicit Go scheduler yield, unlike usually preemptive OS scheduling. section 3.3.1
The Stingy and Spendy race
Two goroutines repeatedly add to and subtract from a shared bank-account variable. On one processor, non-preemptive scheduling may make the race less visible, but parallel execution can interleave reads and writes. Runs can produce 4,203,750 or −1,127,120 instead of the expected balance, so reducing processors is not a reliable fix. section 3.3.1
