Функция runtime.Gosched
Функция runtime.Gosched передает управление другим горутинам,
приостанавливая текущую горутину и позволяя планировщику
выполнить другие готовые к выполнению горутины. После того как
другие горутины завершат свою работу или также передадут управление,
выполнение текущей горутины будет продолжено. Эта функция
полезна в ситуациях, когда необходимо дать возможность выполниться
другим горутинам, особенно в бесконечных циклах.
Синтаксис
runtime.Gosched()
Пример 1
Давайте рассмотрим базовый пример использования
runtime.Gosched для передачи управления между горутинами:
package main
import (
"fmt"
"runtime"
)
func main() {
go func() {
for i := 0; i < 5; i++ {
fmt.Println("Goroutine 1:", i)
runtime.Gosched()
}
}()
go func() {
for i := 0; i < 5; i++ {
fmt.Println("Goroutine 2:", i)
runtime.Gosched()
}
}()
fmt.Scanln()
}
Результат выполнения кода может выглядеть так (порядок может меняться):
"Goroutine 1: 0"
"Goroutine 2: 0"
"Goroutine 1: 1"
"Goroutine 2: 1"
"Goroutine 1: 2"
"Goroutine 2: 2"
"Goroutine 1: 3"
"Goroutine 2: 3"
"Goroutine 1: 4"
"Goroutine 2: 4"
Пример 2
Использование runtime.Gosched в бесконечном цикле
для предотвращения блокировки других горутин:
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
done := make(chan bool)
go func() {
for {
select {
case <-done:
fmt.Println("Worker stopped")
return
default:
fmt.Println("Working...")
runtime.Gosched()
time.Sleep(100 * time.Millisecond)
}
}
}()
time.Sleep(500 * time.Millisecond)
done <- true
time.Sleep(100 * time.Millisecond)
}
Результат выполнения кода:
"Working..."
"Working..."
"Working..."
"Working..."
"Worker stopped"
Пример 3
Сравнение работы с runtime.Gosched и без нее
в интенсивных вычислениях:
package main
import (
"fmt"
"runtime"
"time"
)
func heavyTask(id int) {
sum := 0
for i := 0; i < 100000000; i++ {
sum += i
if i%1000000 == 0 {
runtime.Gosched()
}
}
fmt.Printf("Task %d completed, sum: %d\n", id, sum)
}
func main() {
start := time.Now()
for i := 0; i < 3; i++ {
go heavyTask(i)
}
time.Sleep(1 * time.Second)
fmt.Println("Main goroutine continues...")
time.Sleep(1 * time.Second)
fmt.Println("Main goroutine finished")
}
Результат выполнения кода:
"Main goroutine continues..."
"Task 0 completed, sum: 4999999950000000"
"Task 1 completed, sum: 4999999950000000"
"Task 2 completed, sum: 4999999950000000"
"Main goroutine finished"
Пример 4
Пример с тремя горутинами, где каждая передает управление после выполнения части работы:
package main
import (
"fmt"
"runtime"
)
func process(id int, steps int) {
for i := 1; i <= steps; i++ {
fmt.Printf("Goroutine %d: step %d\n", id, i)
if i%2 == 0 {
runtime.Gosched()
}
}
}
func main() {
go process(1, 5)
go process(2, 5)
go process(3, 5)
fmt.Scanln()
}
Результат выполнения кода (порядок может меняться):
"Goroutine 1: step 1"
"Goroutine 2: step 1"
"Goroutine 3: step 1"
"Goroutine 1: step 2"
"Goroutine 2: step 2"
"Goroutine 3: step 2"
"Goroutine 1: step 3"
"Goroutine 2: step 3"
"Goroutine 3: step 3"
"Goroutine 1: step 4"
"Goroutine 2: step 4"
"Goroutine 3: step 4"
"Goroutine 1: step 5"
"Goroutine 2: step 5"
"Goroutine 3: step 5"
Смотрите также
-
функцию
runtime.GOMAXPROCS,
которая устанавливает количество одновременно выполняющихся потоков -
функцию
runtime.NumGoroutine,
которая возвращает количество активных горутин -
функцию
runtime.Goexit,
которая завершает выполнение текущей горутины -
функцию
runtime.NumCPU,
которая возвращает количество доступных процессоров