go語言併發程式設計

2021-08-15 18:01:55 字數 2858 閱讀 3135

協程(coroutine)本質上是一種使用者態執行緒,不需要作業系統來進行搶占式排程,且在真正的實現中寄存於執行緒中,系統開銷極小。

package main

import

"fmt"

func count(ch chan

int,i int)

func main()

for _, ch := range(chs)

}

channel宣告和定義

//宣告乙個傳遞型別為int的channel:

var ch chan

int//或者,我們宣告乙個map,元素是bool型的channel:

var m map[string] chan

bool

//定義乙個channel也很簡單,直接使用內建的函式make()即可:

ch := make(chan

int)

//將乙個資料寫入(傳送)至channel的語法很直觀,如下:

ch <- value

//從channel中讀取資料的語法是

value := <-ch

select

通過呼叫select()函式來監控一系列的檔案控制代碼,一旦其中乙個檔案控制代碼發生了io動作,該select()呼叫就會被返回。

select 

//我們可以實現乙個有趣的程式:

ch := make(chan

int,1)

for

i := <-ch

fmt.println("value received:", i)

}//這個程式實現了乙個隨機向ch中寫入乙個0或者1的過程。當然,這是個死迴圈。

緩衝機制

要建立乙個帶緩衝的channel,其實也非常容易:

c := make(chan

int,1024)

在呼叫make()時將緩衝區大小作為第二個引數傳入即可,比如上面這個例子就建立了乙個大小為1024的int型別channel,即使沒有讀取方,寫入方也可以一直往channel裡寫入,在緩衝區被填完之前都不會阻塞。

我們可以使用range關鍵來實現更為簡便的迴圈讀取:

for i := range c
超時機制

實現超時機制:

// 首先,我們實現並執行乙個匿名的超時等待函式

timeout := make(chan

bool,1)

gofunc() ()

// 然後我們把timeout這個channel利用起來

select

超時機制只是使用了乙個channel+延時來完成的。這種寫法看起來是乙個小技巧,但卻是在go語言開發中避免channel通訊超時的最有效方法。

單向channel

單向channel變數的宣告非常簡單,如下:

var ch1 chan

int// ch1是乙個正常的channel,不是單向的

var ch2 chan

<- float64

// ch2是單向channel,只用於寫float64資料

var ch3 <-chan

int// ch3是單向channel,只用於讀取int資料

channel是乙個原生型別,因此不僅支援被傳遞,還支援型別轉換。

單向channel和雙向channel之間進行轉換:

ch4 := make(chan

int)

ch5 := <-chan

int(ch4) // ch5就是乙個單向的讀取channel

ch6 := chan

<- int(ch4) // ch6 是乙個單向的寫入channel

從設計的角度考慮,所有的**應該都遵循「最小許可權原則」,從而避免沒必要地使用氾濫問題.單向channel也是起到這樣的一種契約作用。

單向channel的用法:

func parse(ch <-chan

int)

}

除非這個函式的實現者無恥地使用了型別轉換,否則這個函式就不會因為各種原因而對ch

進行寫,避免在ch中出現非期望的資料,從而很好地實踐最小許可權原則。

關閉channel

關閉channel非常簡單,直接使用go語言內建的close()函式即可:

close(ch)//判斷乙個channel是否已經被關閉:

x, ok := <-ch

同步鎖

go語言包中的sync包提供了兩種鎖型別:sync.mutex和sync.rwmutex。mutex是最簡單的一種鎖型別,同時也比較暴力,當乙個goroutine獲得了mutex後,其他goroutine就只能乖乖等到這個goroutine釋放該mutex。rwmutex相對友好些,是經典的單寫多讀模型。

對於這兩種鎖型別,任何乙個lock()或rlock()均需要保證對應有unlock()或runlock()

典型使用模式如下:

var l sync.mutex

func foo()

全域性唯一性操作

從全域性的角度只需要執行一次的**,比如全域性初始化操作,go語言提供了乙個once型別來保證全域性的唯一性操作

var a string

var once sync.once

func setup()

func doprint()

func twoprint()

Go語言併發程式設計(二)

使用非常簡單,在函式前增加乙個go 例 go f a,b 開啟後,不等待其結束,主線程繼續執行。ps 要注意的是乙個goroutine開啟後,若不等其執行,main 主goroutine 中將繼續執行下一步,那麼主線程一結束,goroutine中的程式就不會執行了。如何解決?如下 func says...

Go語言 併發程式設計goroutine

在go語言中併發是通過goroutine實現。goroutine類似於執行緒,屬於使用者態執行緒。go語言也可以通過channel 管道 與多個goroutine進行通訊。goroutine類似於執行緒,在go語言中底層分配了乙個執行緒池,因此不需要我們對其進行管理,由go執行時的routine進行...

Go語言併發程式設計 讀寫鎖

通過對互斥鎖的學習,我們已經了解了鎖的概念及用途。主要用於處理併發中的臨界資源問題。rwmutex是基於mutex實現的,唯讀鎖的實現使用類似引用計數器的功能。rwmutext是讀 寫互斥鎖。鎖可以由任意數量的讀取器或單個編寫器持有。rwmutex的零值是未鎖定的mutex。當有乙個goroutin...