[golang note] 協程基礎

協程概念


        協程一般稱爲coroutine,在golang中稱爲goroutine。golang

        協程本質上是一種用戶態線程,它不須要操做系統來進行搶佔式調度,在實際實現中寄存在線程之中。編程

        協程系統開銷極小,可有效提升單個線程的任務併發性,從而避免使用多線程。並且使用協程編程簡單,結構清晰。缺點就是須要編程語言的支持,若是不支持,則須要用戶在程序中自行實現調度器。多線程

goroutine


        goroutine是golang中的輕量級線程實現,由go runtime管理。併發

• goroutine使用語法

// 定義協程函數
func MyRoutineFunction(參數列表) (返回值列表) {
    // 函數體
}

// 啓動協程
go MyRoutineFunction(參數列表)

        啓動一個goroutine使用go關鍵字,go是golang中最重要的關鍵字,所以這個語言也是以這個關鍵字命名。編程語言

        在一個函數前加上go關鍵字調用,此次調用就會在一個新的goroutine中併發執行,開啓goroutine的線程將繼續執行函數

        當被go調用的函數返回時,這個goroutine也自動結束了。若是這個函數有返回值,那麼這個返回值會被丟棄oop

        golang程序從main()函數開始執行,當main()函數返回時,程序結束且不等待其餘goroutine結束spa

• goroutine使用示例

package main

import (
    "fmt"
    "time"
)

func Add(x, y int) {
    z := x + y
    fmt.Println(z)
}

func main() {
    for i := 0; i < 10; i++ {
        go Add(i, i)
    }

    fmt.Println("main goroutine finished!")
    time.Sleep(3 * time.Second)
}

       程序運行兩次的結果以下:
操作系統

       能夠看出goroutine看上去的確是併發執行,結果具備不肯定性。線程

併發與並行


• 概念

      

        兩個隊列,一個Coffee機器,那是併發。

        兩個隊列,兩個Coffee機器,那是並行。

• golang併發與並行

▶  併發執行

        若是在單核cpu狀況下,golang全部的goroutine只能在一個線程裏跑 。

        若是當前goroutine不發生阻塞,它是不會讓出cpu時間給其餘goroutine,除非調用runtime.Gosched()主動讓出時間片。

       若是當前goroutine發生阻塞,它會主動讓出cpu時間給其餘goroutine執行。

        golang的runtime包是goroutine的調度器,其中使用runtime.GOMAXPROCS(n)能夠控制使用cpu核數。

▪ 例子一

package main

import "fmt" import "time"
import "runtime"
func loop() { fmt.Println("loop starts!") for i := 0; i < 10; i++ { fmt.Printf("%d ", i) } fmt.Println() } func main() {
runtime.GOMAXPROCS(1) // 強制使用1個cpu
go loop() go loop() time.Sleep(
3 * time.Second) }

       運行結果以下:

▪ 例子二

package main

import (
    "fmt"
"runtime"
"time" ) func Add(x, y int) { z := x + y fmt.Println(z) } func main() {
runtime.GOMAXPROCS(1) // 強制使用1個cpu
go Add(
0, 0) go Add(1, 1) go Add(2, 2) go Add(3, 3) go Add(4, 4) go Add(5, 5) go Add(6, 6) go Add(7, 7) go Add(8, 8) go Add(9, 9) fmt.Println("main goroutine finished!") time.Sleep(3 * time.Second) }

       運行結果以下:

▶  並行執行

        默認狀況下,golang是開啓多核的,所以一開始的示例中的輸出就是無序的。

        咱們也能夠告訴golang咱們容許同時最多使用核數。

▪ 例子一

package main

import "fmt" import "time" import "runtime" func loop() {
    fmt.Println("loop starts!")
    for i := 0; i < 10; i++ {
        fmt.Printf("%d ", i)
    }
    fmt.Println()
}

func main() {
    runtime.GOMAXPROCS(2)

    go loop()
    go loop()
    go loop()
    go loop()

    time.Sleep(3 * time.Second)
}

       多運行幾回,能夠獲得結果:

相關文章
相關標籤/搜索