Оператор go запускает функцию в отдельном потоке выполнения.
Вы можете начать новый поток выполнения, goroutine, с помощью оператора go. Он запускает функцию в другой, недавно созданной goroutine. Все goroutines в одной программе имеют одинаковое адресное пространство.
go list.Sort() // Запустить list.Sort параллельно; не ждите этого.
Следующая программа напечатает "Привет из главной goroutine". Также может быть напечатано "Привет из другой goroutine", в зависимости от того, какая из двух goroutine завершится первой.
func main() {
go fmt.Println("Привет из другой goroutine")
fmt.Println("Привет из главной goroutine")
// На этом этапе выполнение программы останавливается
// и все активные goroutines убиты.
}
Следующая программа, скорее всего, напечатает "Привет из главной goroutine" и "Привет из другой goroutine". Они могут быть напечатаны в любом порядке. Еще одна возможность заключается в том, что вторая goroutine чрезвычайно медленная и не печатает свое сообщение до завершения программы.
func main() {
go fmt.Println("Привет из другой goroutine")
fmt.Println("Привет из главной goroutine")
// даем время другой goroutine завершиться
time.Sleep(time.Second)
}
Вот несколько более реалистичный пример, где мы определяем функцию, которая использует конкурентность для отсрочки события.
// Publish выводит текст на стандартный вывод
// по истечении заданного времени.
// Она не блокируется, но сразу возвращается.
func Publish(text string, delay time.Duration) {
go func() {
time.Sleep(delay)
fmt.Println("BREAKING NEWS:", text)
}() // Обратите внимание на круглые скобки.
// Мы должны вызвать анонимную функцию.
}
Вот как вы можете использовать функцию Publish.
func main() {
Publish("goroutine запускается в новом потоке", 5*time.Second)
fmt.Println("Будем надеяться, что новости будут опубликованы до того как я выйду")
// Дождаться публикации новостей.
time.Sleep(10 * time.Second)
fmt.Println("Десять секунд спустя: я выхожу сейчас")
}
Программа, скорее всего, напечатает эти три строки в указанном порядке и с пятисекундным перерывом между каждой строкой.
$ go run publish1.go
Будем надеяться, что новости будут опубликованы до того как я выйду
BREAKING NEWS: goroutine запускается в новом потоке
Десять секунд спустя: я выхожу сейчас
В общем случае невозможно организовать, чтобы потоки ждали друг друга за счет Sleep. Основным методом синхронизации в Go является использование каналов.
Реализация
Goroutines легки, стоят немного больше, чем выделение стекового пространства. Стеки начинаются с малого и растут, выделяя и освобождая хранилище кучи по мере необходимости.
Внутренние goroutines действуют как сопрограммы (coroutines), которые мультиплексируются между несколькими потоками операционной системы. Если одна goroutine блокирует поток ОС, например, ожидая ввода, другие goroutines в этом потоке будут мигрировать, чтобы продолжить работу.
Читайте также:
Комментариев нет:
Отправить комментарий