<p dir="auto">If you run this code with only one go routine:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="package main

import &quot;fmt&quot;
import &quot;runtime&quot;
import &quot;time&quot;

func cpuIntensive(p *int) {
  for i := 1; i &lt;= 100000000000; i++ {
    *p = i
  }
}

func main() {
  runtime.GOMAXPROCS(1)

  x := 0
  go cpuIntensive(&amp;x)

  time.Sleep(100 * time.Millisecond)

  // printed only after cpuIntensive is completely finished
  fmt.Printf(&quot;x = %d.\n&quot;, x)
}"><pre class="notranslate"><code class="notranslate">package main

import "fmt"
import "runtime"
import "time"

func cpuIntensive(p *int) {
  for i := 1; i &lt;= 100000000000; i++ {
    *p = i
  }
}

func main() {
  runtime.GOMAXPROCS(1)

  x := 0
  go cpuIntensive(&amp;x)

  time.Sleep(100 * time.Millisecond)

  // printed only after cpuIntensive is completely finished
  fmt.Printf("x = %d.\n", x)
}
</code></pre></div>
<p dir="auto">Scheduler is paralized, and Printf is NOT printed after 100ms as expected, but after all  job is done in cpuintensive()  go routine.</p>
<p dir="auto">But if programmer insert <code class="notranslate">runtime.Gosched()</code> in intensive for loop of routine, cooperative scheduler works  fine.</p>
<p dir="auto">Is this by design or are there plans to make Golang scheduler preemptive?</p>
<p dir="auto">Currently goroutines are only preemptible at function call points. Hence, it's possible to write a tight loop (e.g., a numerical kernel or a spin on an atomic) with no calls or allocation that arbitrarily delays preemption. This can result in arbitrarily long pause times as the GC waits for all goroutines to stop.</p>
<p dir="auto">In unusual situations, this can even lead to deadlock when trying to stop the world. For example, the runtime's TestGoroutineParallelism tries to prevent GC during the test to avoid deadlock. It runs several goroutines in tight loops that communicate through a shared atomic variable. If the coordinator that starts these is paused part way through, it will deadlock.</p>
<p dir="auto">One possible fix is to insert preemption points on control flow loops that otherwise have no preemption points. Depending on the cost of this check, it may also require unrolling such loops to amortize the overhead of the check.</p>
<p dir="auto">This has been a longstanding issue, so I don't think it's necessary to fix it for 1.5. It can cause the 1.5 GC to miss its 10ms STW goal, but code like numerical kernels is probably not latency-sensitive. And as far as I can tell, causing a deadlock like the runtime test can do requires looking for trouble.</p>
<p dir="auto"><a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/RLH/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/RLH">@RLH</a></p>