Why is time.sleep required to run certain goroutines?

浪尽此生 提交于 2019-11-28 19:13:53

If you remove the time.Sleep you don't give the say("world") goroutine a chance to run. The goroutine scheduler is not preemptive. Your goroutines have to give up control before another goroutine will run. One way to give up control is to run time.Sleep.

If you take out the time.Sleep from the say function then the primary goroutine runs 5 times without giving up control to the secondary goroutine and then when the primary goroutine returns from say the program exits because there is nothing to keep the program alive.

Rick-777

Because the goroutine scheduler is not preemptive, your goroutines have to give up control before another goroutine will run. One way to give up control is with time.Sleep. Another way is with runtime.Gosched().

Here's the tutorial modified to use Gosched(): http://play.golang.org/p/jQ9mlGYXXE

This is a useful lesson in understanding goroutines. However, trying to control the scheduler directly is definitely an anti-pattern; grief will often follow.

Instead, think more about the goroutines like chunks of communicating digital hardware (state machines are a good analogy). It's better to learn about the Communicating Sequential Processes model on which goroutines are based. In a CSP-based design, each goroutine has its own private state and exchanges messages to interact with the state of other goroutines. The passing of messages forces synchronization, which the scheduler uses to determine what activity gets cpu time and what gets put in a wait queue.

When you approach Go this way, you probably never need to worry about scheduler internals.

If you remove time.Sleep from the say function the main will execute say("hello") and terminate without executing the goroutine. If you add a time.Sleep (or otherwise a select {}) before the main end it will give time to the goroutine to run and that thread will be picked from the scheduler.

Example:

package main

import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        // time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world")
    say("hello")

    time.Sleep(1*time.Second)
    // Vs: 
    // select {} // blocks indefinitely, requires manual interrupt
          // In CSP-speak the empty select is like STOP.
          // for{} would cause the cpu to max and the process's STATE will be `running`
          // select{} will not cause the cpu to max and the process state will be `sleeping`
}

The output will usually be 5 hello followed by 5 world but it could also manage to print one of the world before the last hello

TRY IT --> (http://) goo.gl/K2v7H0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!