Go goroutine
阿新 • • 發佈:2018-07-25
idt ima 不支持 時區 min 如果 hello 兩個 cond
2018-07-25 16:40:10
goroutine
Go語言協程
定義
任何函數只需要加上go就能送給調度器運行
不需要在定義時區分是否是異步函數(這點是針對Python3.5引入的async def定義時說明自己是一個協程)
調度器在合適的點進行切換(非搶占式的,但切換點也不是任意的點,傳統是需要顯示寫出來,goroutine不需要)
可能切換的點:I/O,select ; channel ;等待鎖;函數調用(有時);runtime.Gosched()
註意:以上只是參考,不能保證切換,不能保證在其他地方不切換
使用-race來檢測數據訪問沖突
代碼
goroutine.go
package main import ( "fmt" "time" ) //註意:兩個i都是i沒關系的 其余語言10/100個並發執行可以,但是1000個就很難啦 func main() { for i := 0; i < 1000; i++ { go func(i int) { //開goroutine 這裏寫成一個匿名函數要方便點 for { fmt.Printf("Hello from goroutine %d\n", i) //Printf是一個io操作 由協程之間切換 } }(i) } time.Sleep(time.Minute)//如果沒有這句話 是沒有輸出的 因為開了1000個goroutine還沒來得及輸出就完了 }
查看系統究竟起了多少個線程?
top命令查看:CPU 占用率 #TH線程(根據系統核來)
Coroutine協程
子程序是協程的一個特例
協程特點:
輕量級”線程”
非搶占式多任務處理,由協程主動交出控制權
編譯器/解釋器/虛擬機層面的多任務
多個協程可在一個或多個線程在工作
func main() { var a [10]int
for i := 0; i<10 ; i++ {
go func(i int) { //沒有i race condition
for{
a[i]++ //每個人都不斷的去做加法 沒有協程之間切換 沒辦法交出控制權runtime.Gosched() //手動交出控制權 一般很少用 如果沒有這句,該例子程序會陷入死循環
}
}(i) //沒有i 會報錯 index out of range
}
time.Sleep(time.Millisecond)
fmt.Println(a)
}
普通函數與協程對比:doWork做完了才把控制權交給main
其他語言對協程支持
Go語言原生支持
C++:通過Boost.Coroutine庫支持
Java:不支持 (並不是完全不支持,有第三方的)
Python中:Python3.5以前使用yield關鍵字實現協程,Python3.5加入了async def 對協程原生支持
Go goroutine