併發概念程序員
Go是併發語言,而非並行語言。併發性是同時處理許多事情的能力。並行性parallelism指能夠同時作不少事情。併發
Go中使用Goroutines來實現併發concurently。Goroutines是與其餘函數或方法同時運行的函數或方法。異步
Goroutines被認爲是輕量級的線程,與線程相比,建立Goroutines成本很小,故Go應用程序能夠併發執行數千個Goroutines。async
不須要在定義時區分是不是異步函數(這點是針對Python3.5引入的async def定義時說明本身是一個協程)函數
調度器在合適的點進行切換(非搶佔式的,但切換點也不是任意的點,傳統是須要顯示寫出來,goroutine不須要)spa
可能切換的點:I/O,select ; channel ;等待鎖;函數調用(有時);runtime.Gosched()線程
注意:以上只是參考,不能保證切換,不能保證在其餘地方不切換設計
使用-race來檢測數據訪問衝突3d
任何函數或方法調用前面加上go就能送給調度器運行 ,運行一個新的Goroutine。code
例子:
goroutine.go
輸出是:Hello from goroutine 隨機打印的值
查看系統究竟起了多少個線程?
top命令查看:CPU 佔用率 #TH線程(根據系統核來)
子程序是協程的一個特例
協程特色:
輕量級」線程」
非搶佔式多任務處理,由協程主動交出控制權
編譯器/解釋器/虛擬機層面的多任務
多個協程可在一個或多個線程在工做
啓動多個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規則:
例子:
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 對協程原生支持