Go語言之併發程式設計(一)

2022-04-05 05:52:30 字數 2809 閱讀 1503

輕量級執行緒(goroutine)

雖然,執行緒池為邏輯編寫者提供了執行緒分配的抽象機制。但是,如果面對隨時隨地可能發生的併發和執行緒處理需求,執行緒池就不是非常直觀和方便了。能否有一種機制:使用者分配足夠多的任務,系統能自動幫助使用者把任務分配到cpu上,讓這些任務盡量併發運作。這種機制在go語言中被稱為goroutine。

goroutine的概念類似於執行緒,但goroutine由go程式執行時的排程和管理。go程式會自動將goroutine中的任務分配給cpu。

建立goroutine

go程式中使用go關鍵字為乙個函式建立乙個goroutine。乙個函式可以被建立多個goroutine,乙個goroutine必定對應乙個函式。為乙個普通函式建立goroutine的寫法如下:go 函式名(引數列表)。

函式名:要呼叫的函式名。

引數列表:呼叫函式需要傳入的引數。

package main

import (

"fmt"

"time"

)func running(id, limit int) }}

func main()

執行結果:  

id: 2 tick:1

id: 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 main

import (

"fmt"

"time"

)func main()

} }(1, 5)

var input string

fmt.scanln(&input)

}

執行結果:

id: 1 tick:1

id: 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...