Подтвердить что ты не робот

Почему требуется время для выполнения определенных goroutines?

В уроке GO у нас есть этот слайд: Goroutines

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")
}

Запуск этого кода дает ожидаемые результаты ("мир" и "привет" записываются на экран взаимозаменяемо 5 раз).

Однако, если мы закомментируем time.Sleep (и, следовательно, строку "time" импорта) и снова запустим программу, у нас останется only "привет", записанная на экран пять раз.

Что такого важного в time.Sleep, которое спасает горутин от смерти?

4b9b3361

Ответ 1

Если вы удалите time.Sleep, вы не дадите gotoutine say("world") шанс на запуск. Планировщик goroutine не является превентивным. Ваши goroutines должны отказаться от контроля до того, как другой goroutine будет работать. Один из способов отказаться от управления - запустить time.Sleep.

Если вы вытащите time.Sleep из функции say, тогда первичный goroutine запускается 5 раз, не отказываясь от управления вторичной goroutine, а затем, когда первичный goroutine возвращается из say, программа выходит из-за того, что ничего нет для сохранения программы.

Ответ 2

Поскольку планировщик процедур не имеет преимуществ, ваши программы должны отказаться от контроля, прежде чем будет запущена другая программа. Один из способов отказаться от управления с помощью time.Sleep. Другой способ - с runtime.Gosched().

Вот учебник, модифицированный для использования Gosched(): http://play.golang.org/p/jQ9mlGYXXE

Это полезный урок в понимании горутин. Однако попытка напрямую управлять планировщиком - это определенно анти-паттерн; часто последует горе.

Вместо этого, подумайте больше о рутинных программах, таких как блоки обмена цифровым оборудованием (конечные автоматы - хорошая аналогия). Лучше узнать о модели последовательных процессов, на которой основаны процедуры. В схеме на основе CSP каждая goroutine имеет свое собственное частное состояние и обменивается сообщениями для взаимодействия с состоянием других goroutines. Передача сообщений вызывает синхронизацию, которую планировщик использует для определения того, какое действие получает процессорное время, а какое - в очередь ожидания.

Когда вы подходите к Go таким образом, вам, вероятно, никогда не придется беспокоиться о внутренностях планировщика.

Ответ 3

Если вы удаляете time.Sleep из функции say, main выполнит say ( "hello" ) и завершится без выполнения goroutine. Если вы добавите time.Sleep(или иначе выберите {}) до основного конца, он даст время для запуска goroutine и этот поток будет выбран из планировщика.

Пример:

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 STATE will be `running`
          // select{} will not cause the cpu to max and the process state will be `sleeping`
}

Вывод обычно будет 5 привет, а затем 5 мира, но он также может распечатать один из миров до последнего приветствия

ПОПРОБУЙТЕ ИТ → (http://) goo.gl/K2v7H0