輕量級執行緒(goroutine)
雖然,執行緒池為邏輯編寫者提供了執行緒分配的抽象機制。但是,如果面對隨時隨地可能發生的併發和執行緒處理需求,執行緒池就不是非常直觀和方便了。能否有一種機制:使用者分配足夠多的任務,系統能自動幫助使用者把任務分配到cpu上,讓這些任務盡量併發運作。這種機制在go語言中被稱為goroutine。
goroutine的概念類似於執行緒,但goroutine由go程式執行時的排程和管理。go程式會自動將goroutine中的任務分配給cpu。
建立goroutine
go程式中使用go關鍵字為乙個函式建立乙個goroutine。乙個函式可以被建立多個goroutine,乙個goroutine必定對應乙個函式。為乙個普通函式建立goroutine的寫法如下:go 函式名(引數列表)。
函式名:要呼叫的函式名。
引數列表:呼叫函式需要傳入的引數。
package mainimport (
"fmt"
"time"
)func running(id, limit int) }}
func main()
執行結果:
id: 2 tick:1id: 1 tick:1
id: 1 tick:2
id: 2 tick:2
id: 2 tick:3
id: 1 tick:3
id: 2 tick:4
id: 1 tick:4
id: 2 tick:5
id: 1 tick:5
id: 2 tick:6
**執行後,命令行會不斷輸出tick直到times滿足limit跳出迴圈,goroutine終止。同時可以使用fmt.scanln接受使用者輸入,這兩個環節可以同時進行。
使用匿名函式建立goroutine
go關鍵字後也可以為匿名函式或閉包啟動goroutine。使用匿名函式或閉包建立goroutine時,除了將函式定義部分寫在go的後面之外,還需要加上匿名函式的呼叫引數,格式如下::
go func(引數列表)(呼叫引數列表)
引數列表:函式體內的引數變數列表。
函式體:匿名函式的**。
呼叫引數列表:啟動goroutine時,需要向匿名函式傳遞的呼叫引數。
package mainimport (
"fmt"
"time"
)func main()
} }(1, 5)
var input string
fmt.scanln(&input)
}
執行結果:
id: 1 tick:1id: 1 tick:2
id: 1 tick:3
id: 1 tick:4
id: 1 tick:5
因為goroutine在main()函式結束時會一同結束,所以在main函式的末尾都加上fmt.scanln函式,等待使用者輸入後才會結束main函式
調整併發的執行效能(gomaxprocs)
在go程式執行時(runtime)實現了乙個小型的任務排程器。這套排程器的工作原理類似於作業系統排程執行緒,go程式排程器可以高效地將cpu資源分配給每乙個任務。傳統邏輯中,開發者需要維護執行緒池中線程與cpu核心數量的對應關係。同樣的,go中也可以通過runtime.gomaxprocs()函式做到,格式為:
runtime.gomaxprocs(邏輯cpu數量)
這裡的邏輯cpu數量可以有如下幾種數值:
一般情況下,可以使用runtime.numcpu()查詢cpu數量,並使用runtime.gomaxprocs()函式進行設定,例如:
runtime.gomaxprocs(runtime.numcpu())
go1.5版本之前,預設使用的是單核心執行。從go1.5版本開始,預設執行上面語句以便讓**併發執行,最大效率地利用cpu。gomaxprocs同時也是乙個環境變數,在應用程式啟動前設定環境變數也可以起到相同的作用。
併發和並行
在講解併發概念時,總會涉及另外乙個概念並行。下面讓我們來了解併發和並行之間的區別。
兩個概念的區別是:任務是否同時執行。舉個栗子:
go語言在gomaxprocs 數量與任務數量相等時,可以做到並行執行,但一般情況下都是併發執行。
goroutine和coroutine的區別
c#、lua、python語言都支援coroutine特性。coroutine與goroutine在名字上類似,都可以將函式或者語句在獨立的環境中執行,但是它們之間有兩點不同:
狹義地說,goroutine可能發生在多執行緒環境下,goroutine無法控制自己獲取高優先度支援;coroutine始終發生在單執行緒,coroutine程式需要主動交出控制權,宿主才能獲得控制權並將控制權交給其他coroutine。
coroutine的執行機制屬於協作式任務處理,早期的作業系統要求每乙個應用必須遵守作業系統的任務處理規則,應用程式在不需要使用cpu時,會主動交出cpu使用權。如果開發者無意間或者故意讓應用程式長時間占用cpu,作業系統也無能為力,表現出來的效果就是計算機很容易失去響應或者宕機。
goroutine屬於搶占式任務處理,已經和現有的多執行緒和多程序任務處理非常類似。應用程式對cpu的控制最終還需要由作業系統來管理,作業系統如果發現乙個應用程式長時間大量地占用cpu,那麼使用者有權終止這個任務。
Go語言之併發程式設計(四)
同步 go 程式可以使用通道進行多個 goroutine 間的資料交換,但這僅僅是資料同步中的一種方法。通道內部的實現依然使用了各種鎖,因此優雅 的代價是效能。在某些輕量級的場合,原子訪問 atomic包 互斥鎖 sync.mutex 以及等待組 sync.waitgroup 能最大程度滿足需求。當...
Go語言之併發程式設計(三)
telnet回音伺服器 telnet協議是tcp ip協議族中的一種。它允許使用者 telnet客戶端 通過乙個協商過程與乙個遠端裝置進行通訊。本例將使用一部分telnet協議與伺服器進行通訊。伺服器的網路庫為了完整展示自己的 實現了完整的收發過程,一般比較傾向於使用傳送任意封包返回原資料的邏輯。這...
Go語言之併發示例 Pool 一
這篇文章演示使用有緩衝的通道實現乙個資源池,這個資源池可以管理在任意多個goroutine之間共享的資源,比如網路連線 資料庫連線等,我們在資料庫操作的時候,比較常見的就是資料連線池,也可以基於我們實現的資源池來實現。可以看出,資源池也是一種非常流暢性的模式,這種模式一般適用於在多個goroutin...