为何要使用 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线程

相关文章
相关标签/搜索