Golang 協程(goroutine) 運行過程 與 併發

首先咱們須要理解進程和線程的關係算法

當運行一個應用程序的時候,操做系統會爲這個應用程序啓動一個進程,該個進程包含了應用程序在運行中所用須要用到和維護的各類資源的容器網絡

  • 每一個進程至少包含一個線程
  • 每一個進程的初始線程被稱爲主線程
  • 執行線程的空間是應用程序自己的空間
  • 主線程終止,應用程序也將終止

goroutine執行過程

前提, goroutine的執行主要依靠調度處理器來完成,如
// 建立了兩個調度處理器
runtime.GOMAXPROCS(2)

一、建立一個goroutine
二、goroutine進入調度處理器全局運行隊列(調度器)中
三、調度器分配一個調度處理器供goroutine使用
四、goroutine 執行併發

在其上述執行過程當中,咱們很容易會思考到一個問題,例如如今有 3 個goroutine等待執行,那麼,goroutine是如何運行的呢操作系統

咱們來嘗試執行一段代碼線程

import (
"fmt"
"runtime"
"sync"
)

func main()  {
    // 建立一個調度處理器
    runtime.GOMAXPROCS(1)

    var wg sync.WaitGroup
    wg.Add(2)

    fmt.Println("協程開始 ...\n")

    go func() {
        defer wg.Done()

        for count :=0; count < 3; count++ {
            for char := 'a'; char < 'a' + 26; char ++ {
                fmt.Printf("%c", char)
            }
        }
    }()

    go func() {
        defer wg.Done()

        for count :=0; count < 3; count++ {
            for char := 'A'; char < 'A' + 26; char ++ {
                fmt.Printf("%c", char)
            }
        }
    }()

    fmt.Println("wait ...\n")
    wg.Wait()

    fmt.Println("\n結束...")
}

結果debug

協程開始 ...
wait ...
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
結束...

咱們會發現,是否是第二goroutine先執行完畢?是的,無論是嘗試多少次,都會是這個結果code

其實,致使這個問題的緣由來自於其管理goroutine壽命的行爲協程

goroutine中,爲了防止某個goroutine運行時間過長,調度器會中止當前正在運行的goroutine,給其餘goroutine運行的機會隊列

繼續查看代碼進程

package main

import (
"fmt"
"runtime"
"sync"
)

func main()  {
    runtime.GOMAXPROCS(1)

    var wg sync.WaitGroup
    wg.Add(3)

    fmt.Println("協程開始 ...\n")

    go func() {
        defer wg.Done()

        fmt.Println(1)
    }()

    go func() {
        defer wg.Done()

        fmt.Println(2)
    }()
    go func() {
        defer wg.Done()

        fmt.Println(3)
    }()

    fmt.Println("wait ...\n")
    wg.Wait()

    fmt.Println("\n結束...")
}

結果則爲 3 1 2

併發與並行

簡而言之

  • 並行

不用的程序在不一樣的物理處理器上執行,關鍵的在於同時作不少事情

  • 併發

使用較少的資源作更多的事情,即在go中爲,用聰明的算法根據單個物理機器,調度一個個執行

go中,如何實現並行

// 雙核
runtime.GOMAXPROCS(2)

便可

以上,會觸發2兩調度處理器,併發運行,但實際上這種併發也其實就是 go 經過單個物理機器建立多個線程實現的僞並行

IO操做下的goroutine

IO下的goroutine都爲阻塞性的goroutine

  • 資源讀寫IO

調用時,線程將從邏輯處理器上分離,線程繼續堵塞,處理器將綁定一個新的線程,並執行其餘 goroutineIO goroutine 執行完畢後,佔用線程進行回收,下次使用

  • 網絡IO

網絡IO,將從邏輯處理器上分離,且將其放入到網絡輪詢器的運行中,當檢測到改資源IO操做就緒,將取出並分配到邏輯處理器上從新運行

調度器配置

Go 默認支持最多建立10000個線程,若是使用的再多,可能會崩潰,能夠經過runtime或者debug的包來完成這些配置

相關文章
相關標籤/搜索