利用管道(channel)實現同步

2021-10-01 19:52:32 字數 1426 閱讀 3997

go語言實現同步的方式有很多,互斥量(sync.mutex)、channel通訊等等;

今天總結一下go中的channel方式!

channel通訊包含兩種模式:一種是帶無緩衝的channel,另一種是有緩衝的channel;

在無快取的channel上的每一次傳送操作都會有對應的接受操作相配對,傳送和接受操作通常發生在兩個goroutine上(在同乙個goroutine上執行兩個操作容易導致死鎖),無快取的channel上的傳送操作總是在接受操作之前發生;

首先通過無緩衝方式來實現同步:

func

main()

()done <-

1}

根據go語言記憶體模型規範,對於從無緩衝channel進行的接收,發生在對該channel進行的傳送完成之前。因此後台執行緒完成 <- done 接收操作之後,main函式的 done <- 1 傳送操作才有可能完成(從而退出main、退出程式),而此時列印工作已經完成。

上述**雖然可以完成同步,但是對管道的緩衝大小太敏感了,如果管道有緩衝的話就不能夠保證main退出後台執行緒正常列印

更好的做法是將接收和傳送方向調換一下,這樣可以避免同步受緩衝大小的影響;

func

main()

()<-done

}

對於帶緩衝的channel,對於channel的第k個接收完成操作發生在第k+c個傳送操作完成之前,其中c是channel的快取大小。雖然管道是帶快取的,main執行緒接收完成是在後台執行緒傳送開始但還未完成的時刻,此時列印工作也是已經完成的。

基於帶快取的管道,我們可以很容易將列印執行緒擴充套件到n個。下面的例子是開啟10個後台執行緒分別列印:

func

main()

()}// 等待n個後台執行緒完成

for i :=

0; i <

cap(done)

; i++

}

func

main()

()}// 等待n個後台執行緒完成

wg.wait()

}

其中wg.add(1)用於增加等待事件的個數,必須確保在後台執行緒啟動之前執行(如果放到後台執行緒之中執行則不能保證被正常執行到)。當後台執行緒完成列印工作之後,呼叫wg.done()表示完成乙個事件。main函式的wg.wait()是等待全部的事件完成

個人github賬號:

利用管道實現程序間同步

程序間同步是指程序的執行有先後順序,如a程序等待b程序執行完某個動作a程序才能繼續往下執行。程序間通訊的方法都可以用來同步,只是操作是否方便的乙個問題。複習了unix高階程式設計,覺得posix的訊號量是使用起來最方便的。可是無奈程式寫完放到板子裡面跑時,列印提示sem open function ...

Go 利用channel形成管道溝通迴圈內外

這個要解決的問題是,比如如果有乙個大迴圈,取自乙個大的檔案,要進行邏輯處理,那麼這個邏輯的 要放在迴圈每一行的迴圈體裡面,這樣有可能會出現乙個for迴圈的邏輯巢狀,一層又一層,類似俄羅斯套娃.如果放在外面那麼就需要把大迴圈的每一行資料存到乙個陣列或者切片裡面,這樣會佔很大的記憶體 那麼就可以使用這種...

channel 協程同步

與主協程協同 feedadchan make chan struct 1 var feedad model.advertisement if req.withfeedad 釋放主協程 feedadchan struct 主程式 if req.withfeedad case time.after 2 ...