爲何要使用 goroutines 取代 threads

爲何要使用 goroutines 取代 threadsgit

介紹

goroutines 和 threads 都是爲了併發而生。準確的說,並不能說 goroutines 取代 threads。由於其實 goroutines 是創建在一組 threads 之上。將多路併發執行的能力複用在 threads 組上。當某一個 goroutine 須要運行時,會自動將它掛載到一個 thread 上。並且這一系列的調度對開發者是黑盒,無感知的。github

goroutines 對比 threads 的優點

  • 開銷很是便宜,每一個 goroutine 的堆棧只須要幾kb,而且能夠根據應用的須要進行增加和縮小。
  • 一個 thread 能夠對應多個 goroutine,可能一個線程就能夠處理上千個 goroutine。若是該線程中有 goroutine 須要被掛起,等待用戶輸入,那麼會將其餘須要運行的 goroutine 轉移到一個新的 thread 中。全部的這些都被抽象出來,開發者只要面對簡單的 API 就可使用。

使用 goroutine

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) 這句話。由於:golang

  • 當創業一個 goroutine 的時候,會當即返回,執行下語句,並且忽悠全部 goroutine 的返回值;
  • 若是主 goroutine 退出,則其餘任何 goroutine 將不會被執行;
  • 若是你註釋 Sleep 這句話,再運行一次,將會看不到 hello goroutine輸出。

多個 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")
}
複製代碼

輸出爲:bash

a 1 b 2 c 3 d 4 e 5 main terminated
複製代碼

下面表格描述多個 goroutine 執行的時序,能夠看出多個 goroutine 是同時進行的。併發

  • 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: Goroutinesspa

更多內容,歡迎關注個人Github線程

相關文章
相關標籤/搜索