Go goroutine
并發(fā)性Concurrency
并發(fā)概念
Go是并發(fā)語言,而非并行語言。并發(fā)性是同時處理許多事情的能力。并行性parallelism指可以同時做很多事情。
Go中使用Goroutines來實(shí)現(xiàn)并發(fā)concurently。Goroutines是與其他函數(shù)或方法同時運(yùn)行的函數(shù)或方法。
goroutines?
Goroutines被認(rèn)為是輕量級的線程,與線程相比,創(chuàng)建Goroutines成本很小,故Go應(yīng)用程序可以并發(fā)執(zhí)行數(shù)千個Goroutines。
在線程上優(yōu)勢
- 與線程相比,Goroutines非常便宜,只是堆棧大小的幾個kb,堆棧可根據(jù)應(yīng)用程序的需要增長和收縮。而線程情況下,堆棧大小必須指定并且是固定的。
- Goroutines被多路復(fù)用到較少的OS線程,一個程序中可能只有1個線程與數(shù)千個Goroutines,若線程中任何Goroutine都表示等待用戶輸入,則會創(chuàng)建另一個OS線程,剩下的Goroutines被轉(zhuǎn)移到新的OS線程。所有這些都由運(yùn)行時處理,程序員從這些復(fù)雜細(xì)節(jié)中抽象出來,得到一個與并發(fā)工作相關(guān)的干凈的API。
- 使用Goroutines訪問共享內(nèi)存時,通過設(shè)計的通道可以防止競態(tài)條件發(fā)生。通道可以被認(rèn)為時Goroutines通信的管道。
Go語言協(xié)程
定義
不需要在定義時區(qū)分是否是異步函數(shù)(這點(diǎn)是針對Python3.5引入的async def定義時說明自己是一個協(xié)程)
調(diào)度器在合適的點(diǎn)進(jìn)行切換(非搶占式的,但切換點(diǎn)也不是任意的點(diǎn),傳統(tǒng)是需要顯示寫出來,goroutine不需要)
可能切換的點(diǎn):I/O,select? ; channel ;等待鎖;函數(shù)調(diào)用(有時);runtime.Gosched()
注意:以上只是參考,不能保證切換,不能保證在其他地方不切換
使用-race來檢測數(shù)據(jù)訪問沖突
使用
任何函數(shù)或方法調(diào)用前面加上go就能送給調(diào)度器運(yùn)行?,運(yùn)行一個新的Goroutine。
?例子:
例子1:
goroutine.go
輸出是:Hello from goroutine 隨機(jī)打印的值
查看系統(tǒng)究竟起了多少個線程? top命令查看:CPU 占用率 #TH線程(根據(jù)系統(tǒng)核來)?
Goroutine協(xié)程
子程序是協(xié)程的一個特例
協(xié)程特點(diǎn):
輕量級”線程”
非搶占式多任務(wù)處理,由協(xié)程主動交出控制權(quán)?
編譯器/解釋器/虛擬機(jī)層面的多任務(wù)
多個協(xié)程可在一個或多個線程在工作
啟動多個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
普通函數(shù)與協(xié)程對比:doWork做完了才把控制權(quán)交給main。
Goroutine規(guī)則:
- 當(dāng)新Goroutine開始時,Goroutine調(diào)用立即返回,且不等待Goroutine執(zhí)行結(jié)束。
- 當(dāng)Goroutine調(diào)用,并且其任何返回值被忽略之后,go立即執(zhí)行到下一行代碼
- main的Goroutine應(yīng)該為其他的Goroutines執(zhí)行,若main的Goroutine終止了,程序?qū)⒈唤K止,其他Goroutine將不會運(yùn)行。
例子:
func hello() {fmt.Println("Hello world goroutine") } func main() {go hello() //由于main進(jìn)行Sleep,故go hello()有足夠時間在main Goroutine終止之前執(zhí)行time.Sleep(1 * time.Second)fmt.Println("main function") } //輸出是:Hello world goroutine main function?
?
其他語言對協(xié)程支持
Go語言原生支持
C++:通過Boost.Coroutine庫支持
Java:不支持 (并不是完全不支持,有第三方的)
Python中:Python3.5以前使用yield關(guān)鍵字實(shí)現(xiàn)協(xié)程,Python3.5加入了async def 對協(xié)程原生支持
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/ycx95/p/9367128.html
總結(jié)
以上是生活随笔為你收集整理的Go goroutine的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Tunnel Warfare(HDU15
- 下一篇: 51 nod 1049 最大子段和 (简