Зачем использовать горутины вместо потоков

задняя часть Go

Зачем использовать горутины вместо потоков

представлять

И горутины, и потоки созданы для параллелизма. Если быть точным, нельзя сказать, что горутины заменяют потоки. Потому что на самом деле горутины построены на наборе потоков. Возможность мультиплексирования одновременного выполнения мультиплексируется в группе потоков. Когда горутину необходимо запустить, она автоматически монтируется в потоке. Более того, эта серия планирования является черным ящиком для разработчика, незаметным.

Преимущества горутин перед потоками

  • Накладные расходы очень дешевы, стеку требуется всего несколько килобайт на горутину, и он может увеличиваться и уменьшаться в соответствии с потребностями приложения.
  • Поток может соответствовать нескольким горутинам, а один поток может обрабатывать тысячи горутин. Если в потоке есть горутины, которые необходимо приостановить, ожидая ввода пользователя, другие горутины, которые необходимо запустить, будут переданы в новый поток. Все это абстрагируется, и разработчики могут использовать это, столкнувшись с простым API.

использовать горутины

package main

import (
	"fmt"
	"time"
)

func hello() {
	fmt.Println("hello goroutine\r")
}
func main() {
	go hello()
	time.Sleep(1 * time.Second)
	fmt.Println("main function\r")
}

Внимательные ученики обязательно спросят, почему нужно выполнять предложение time.Sleep(1 * time.Second). так как:

  • При запуске горутины она немедленно вернется, выполнит следующий оператор и обманет возвращаемые значения всех горутин;
  • Если основная горутина завершается, никакие другие горутины выполняться не будут;
  • Если вы прокомментируете предложение Sleep и запустите его снова, вы не увидите вывод hello goroutine.

несколько горутин

package main

import (
	"fmt"
	"time"
)

func numbers() {
	for i := 1; i <= 5; i++ {
		time.Sleep(500 * time.Millisecond)
		fmt.Printf("%d ", i)
	}
}
func alphabets() {
	for i := 'a'; i <= 'c'; i++ {
		time.Sleep(1000 * time.Millisecond)
		fmt.Printf("%c ", i)
	}
}
func main() {
	go numbers()
	go alphabets()
	time.Sleep(3000 * time.Millisecond)
	fmt.Println("main terminated")
}

Результат:

a 1 b 2 c 3 d 4 e 5 main terminated

В следующей таблице описывается время выполнения нескольких горутин, и видно, что несколько горутин выполняются одновременно.

  • numbers goroutine
0ms 500ms 1000ms 1500ms 2000ms 2500ms
1 2 3 4 5
  • alphabets goroutine
0ms 400ms 800ms 1200ms 1600ms 2000ms
a b c d e
  • main goroutine
0ms 400ms 500ms 800ms 1000ms 1200ms 1500ms 1600ms 2000ms 2500ms 3000ms
a 1 b 2 c 3 d 4(e) 5

Ссылаться на

Part 21: Goroutines

Чтобы узнать больше, подписывайтесь на меняGithub.