go語言--goroutine

1、goroutine

  • goroutine就是Go語言提供的一種用戶態線程。Go本身實現了goroutine的調度器(Scheduler),Go的調度器由三部分組成:
  • M:指的是Machine,一個M直接關聯了一個內核線程。
  • P:指的processer,表明M所需的上下文環境,也是處理用戶級代碼邏輯的處理器。P的數量能夠經過GOMAXPROCS()來設置,默認值是CPU的核數。
  • G:指的是goroutine,其實本質上也是一種輕量級的線程。

2、goroutine和線程的區別

一、內存佔用

建立一個goroutine大概2KB的棧空間,新建立的線程會佔用1MB的內存空間。併發

二、建立和銷燬的開銷

線程須要從操做系統裏請求資源並在用完以後釋放回去,所以建立和銷燬線程的開銷很是大。
goroutine的建立和銷燬是由運行環境(runtime)完成的,這些操做的開銷就比較小。函數

三、切換開銷

當切換一個線程的時候,調度器須要保存/恢復全部的寄存器。這包括16個通用寄存器,程序指針(program counter),棧指針(stack pointer),段寄存器(segment registers)和16個XMM寄存器,浮點協處理器狀態,16個AVX寄存器,全部的特殊模塊寄存器(MSR)等。當在線程間快速切換的時候這些開銷就變得很是大了
Goroutine的調度是協同合做式的(cooperatively)。當切換goroutine的時候,調度器只須要保存和恢復三個寄存器 - 程序指針,棧指針和DX。切換的開銷就小多了。oop

3、goroutine執行過程

4、goroutine併發

並行:是讓不一樣的代碼片斷同時在不一樣的物理處理器上執行,並行的關鍵是同時作不少事情。
併發:指同時管理不少事情,這些事情可能只作了一半就被暫停去作別的事情了,goroutine是一種併發機制。操作系統

5、goroutine代碼示例

  • 下面例子只會輸出2,不會輸出 1 3,由於當程序優先執行主線程,當主線程執行完後就退出了。
package main

import "fmt"

func main() {

    var i = 3

    go func(a int) {
        fmt.Println(a)
        fmt.Println("1")
    }(i)

    fmt.Println("2")
}
  • 這個例子是分部打印三次大小寫字母,你們能夠把runtime.GOMAXPROCS(2)或者time.Sleep(time.Millisecond)註釋取消掉,再看下運行結果,每次輸出都不同有助於進一步理解goroutine。
package main

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

func main() {

    // 分配一個邏輯處理器給調度器使用
    runtime.GOMAXPROCS(1)

    // wg用來等待程序完成,計數加2,表示要等待兩個goroutine
    var wg sync.WaitGroup
    wg.Add(2)
    fmt.Println("Start Goroutines")

    // 聲明一個匿名函數,並建立一個goroutine
    go func() {
        // 延時調用,在函數退出時調用done來通知main函數工做已經完成
        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 ++  {
                //time.Sleep(time.Millisecond)
                fmt.Printf("%c ", char)
            }
        }
    }()
    fmt.Println("Wating To Finish")
    wg.Wait()
    fmt.Println("\nTerminating Program")
}
相關文章
相關標籤/搜索