[golang note] 協程基礎


協程概念


        協程通常稱為coroutine,在golang中稱為goroutine。

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

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

goroutine


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

• goroutine使用語法

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

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

        啟動一個goroutine使用go關鍵字,go是golang中最重要的關鍵字,因此這個語言也是以這個關鍵字命名。

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

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

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

• 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)
}

       多運行幾次,可以得到結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM