協程(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...