Go goroutine

併發性Concurrency

併發概念程序員

Go是併發語言,而非並行語言。併發性是同時處理許多事情的能力。並行性parallelism指能夠同時作不少事情。併發

Go中使用Goroutines來實現併發concurently。Goroutines是與其餘函數或方法同時運行的函數或方法。異步

goroutines 

Goroutines被認爲是輕量級的線程,與線程相比,建立Goroutines成本很小,故Go應用程序能夠併發執行數千個Goroutines。async

在線程上優點

  • 與線程相比,Goroutines很是便宜,只是堆棧大小的幾個kb,堆棧可根據應用程序的須要增加和收縮。而線程狀況下,堆棧大小必須指定而且是固定的。
  • Goroutines被多路複用到較少的OS線程,一個程序中可能只有1個線程與數千個Goroutines,若線程中任何Goroutine都表示等待用戶輸入,則會建立另外一個OS線程,剩下的Goroutines被轉移到新的OS線程。全部這些都由運行時處理,程序員從這些複雜細節中抽象出來,獲得一個與併發工做相關的乾淨的API。
  • 使用Goroutines訪問共享內存時,經過設計的通道能夠防止競態條件發生。通道能夠被認爲時Goroutines通訊的管道。

Go語言協程

定義

不須要在定義時區分是不是異步函數(這點是針對Python3.5引入的async def定義時說明本身是一個協程)函數

調度器在合適的點進行切換(非搶佔式的,但切換點也不是任意的點,傳統是須要顯示寫出來,goroutine不須要)spa

可能切換的點:I/O,select  ; channel ;等待鎖;函數調用(有時);runtime.Gosched()線程

注意:以上只是參考,不能保證切換,不能保證在其餘地方不切換設計

使用-race來檢測數據訪問衝突3d

使用

任何函數或方法調用前面加上go就能送給調度器運行 ,運行一個新的Goroutine。code

 例子:

例子1:

goroutine.go

輸出是:Hello from goroutine 隨機打印的值

查看系統究竟起了多少個線程?
top命令查看:CPU 佔用率  #TH線程(根據系統核來)

 

Goroutine協程

子程序是協程的一個特例

協程特色:

輕量級」線程」

非搶佔式多任務處理,由協程主動交出控制權 

編譯器/解釋器/虛擬機層面的多任務

多個協程可在一個或多個線程在工做

啓動多個Goroutine

例子1

func numbers() {
    for i := 1; i <= 5; i++ {
        time.Sleep(250 * time.Millisecond)
        fmt.Printf("%d ", i)
    }
}
func alphabets() {
    for i := 'a'; i <= 'e'; i++ {
        time.Sleep(400 * time.Millisecond)
        fmt.Printf("%c ", i)
    }
}
func main() {
    go numbers()
    go alphabets()
    time.Sleep(3000 * time.Millisecond)
    fmt.Println("main terminated")
}
輸出:1 a 2 3 b 4 c 5 d e main terminated

例子2

 

普通函數與協程對比:doWork作完了才把控制權交給main。

Goroutine規則:

  • 當新Goroutine開始時,Goroutine調用當即返回,且不等待Goroutine執行結束。
  • 當Goroutine調用,而且其任何返回值被忽略以後,go當即執行到下一行代碼
  • main的Goroutine應該爲其餘的Goroutines執行,若main的Goroutine終止了,程序將被終止,其餘Goroutine將不會運行。

例子:

func hello() {
    fmt.Println("Hello world goroutine")
}
func main() {
    go hello() //因爲main進行Sleep,故go hello()有足夠時間在main Goroutine終止以前執行
    time.Sleep(1 * time.Second)
    fmt.Println("main function")
}  //輸出是:Hello world goroutine   main function   

 

 

其餘語言對協程支持

Go語言原生支持

C++:經過Boost.Coroutine庫支持

Java:不支持 (並非徹底不支持,有第三方的)

Python中:Python3.5之前使用yield關鍵字實現協程,Python3.5加入了async def 對協程原生支持

相關文章
相關標籤/搜索