使用channel代替條件變數
條件變數訊號傳遞是將條件傳達給一個或多個併發任務的方式,在 Go 標準庫中'sync'包提供了使用條件變數傳送訊號的方法。除此之外、在 golang 中另一種方式是使用內建的 channel
兩種方式都是暫停當前正在執行的 goroutine 並將 CPU 出讓給另一個 goroutine、在此我解釋一下為什麼我更偏向於使用 channel 而不是條件變數傳播訊號到我的 worker goroutines。 使用條件變數遇到的問題: 條件變數的兩個解除阻塞方法:
1、喚醒一個單一的等待 goroutine
2、喚醒一個所有的等待 goroutine
示例如下:
c := sync.NewCond(&sync.Mutex{})
go func() {
c.L.Lock()
c.Wait()
c.L.Unlock()
fmt.Println("DONE")
}()
c.Signal()
理論上,goroutine 將在條件建立訊號時喚醒。一旦發生這種情況,我們應該看到一個字串'DONE'出現、但是由於當前的作業系統是搶佔式的,所以我們不能保證 s.Signal() 一定會在 goroutine 被完全初始化和阻塞之後才呼叫 (無法保證程式執行過程中各個 goroutine 的執行順序)、實際上,對 c.Signal() 的呼叫可以在 Wait() 之前執行,此時程式將退出、我們什麼也看不到、如果我們正在執行的時一個服務、將會有一個 goroutine 處於阻塞狀態、該 goroutine 可能會一直阻塞、直到有訊號來喚醒它。之所以會出現這樣的情況是因為阻塞的 goroutine 可能會錯過 Signal() 或者 Broadcast() 方法的喚醒。 而如果你的程式是一個必須 7*24 小時不間斷執行的服務的話、這樣的情況會使得你的程式 goroutine 持續保持增長直到記憶體 “爆炸”,而你的作業系統最終會因為記憶體溢位而終止該程式 通過 channels 在併發 goroutine 中進行資訊傳遞則可以有效避免這樣的情況、因為 channel 可以通過超時機制終止 goroutine 執行 正常情況下,每次計算機的操作都需要一段時間,它們會在特定的(也許很少的,也許是頻繁的)條件下包含並應該包含停止自身執行的機制。使用 channel 的情況下,我們可以使用 select 語句並新增超時機制。
readyChan := make(chan bool, 1)
go func() {
select {
case <- readyChan:
fmt.Println("HELLO")
case <- time.After(time.Minute):
}
}()
readyChan <- true
如程式碼所示、在使用 channel 的情況下、不會出現 goroutine 一直堆積的情況、如果因為某些原因導致阻塞程式沒有被喚醒 、則在一分鐘的超時期到的時候、goroutine 會優雅地終止 有一些情況,我們想結束所有等待 goroutines。幸運的是,channel 可以關閉,並保持此狀態,以便進一步嘗試從中讀取:
readyChan := make(chan bool, 1)
for i := 0; i < 5; i++ {
go func() {
_, ok := <-readyChan
if !ok {
fmt.Println("Worker ending ...")
return
}
}()
}
close(readyChan)
time.Sleep(3*time.Second)
三秒鐘後,我們將看到嘗試從 channel 中讀取資料的五個 goroutine 返回,因為主 goroutine 剛剛關閉了該 channel。 為什麼要使用緩衝通道? 這兩個示例都使用緩衝 channel,因為如果等待 goroutine 需要很長時間來初始化而且 channel 沒有緩衝,傳送 goroutine 將鎖定並等待,直到 channel 上有一個監聽器。 原文連結:https://zeta.si/page/Using-Go-Channels-Instead-Of-Conditions
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- sql 使用變數帶入in條件SQL變數
- Condition條件變數變數
- pthread 條件變數thread變數
- 關於條件變數變數
- MySQL 變數和條件MySql變數
- SQL Server解惑——查詢條件IN中能否使用變數SQLServer變數
- C++中的條件變數C++變數
- linux 條件變數詳解Linux變數
- 互斥鎖和條件變數 (轉)變數
- 多執行緒06:條件變數執行緒變數
- 程式碼優化-多型代替IF條件判斷優化多型
- Golang 併發程式設計中條件變數的理解與使用Golang程式設計變數
- Linux Qt使用POSIX多執行緒條件變數、互斥鎖(量)LinuxQT執行緒變數
- [題解] 條件變數實現數字的交替輸出變數
- Python執行緒條件變數Condition解析Python執行緒變數
- Python執行緒專題7:條件變數Python執行緒變數
- 動態條件的繫結變數的解決變數
- 多執行緒程式設計介紹-條件變數執行緒程式設計變數
- 秒懂 Golang 中的 條件變數(sync.Cond)Golang變數
- 多執行緒(2)-執行緒同步條件變數執行緒變數
- CentOS下使用MSMTP代替Sendmail傳送郵件CentOSAI
- 在 Web 頁上使用條件數值格式 (轉)Web
- 如何使用ReentrantLock的條件變數,讓多個執行緒順序執行?ReentrantLock變數執行緒
- linux中條件變數和訊號量的區別!Linux變數
- Mysql儲存過程 變數,條件,迴圈語句用法MySql儲存過程變數
- 條件變數的虛假喚醒(spurious wakeups)問題變數
- C++11 中的執行緒、鎖和條件變數C++執行緒變數
- 互斥鎖與條件變數學習與應用小結變數
- oracle只有當where子句中所有條件都使用"=:"才認為是使用繫結變數麼?Oracle變數
- 變數轉化為判斷條件時的各種情況變數
- python多執行緒程式設計5: 條件變數同步Python執行緒程式設計變數
- 全網最詳細的AbstractQueuedSynchronizer(AQS)原始碼剖析(三)條件變數AQS原始碼變數
- muduo網路庫學習筆記(4):互斥量和條件變數筆記變數
- oracle 繫結變數在動態條件統計中的應用Oracle變數
- [20170929]& 代替冒號繫結變數.txt變數
- Excel不同列多條件計數Excel
- 【SQL】SQL中if條件的使用SQL
- PbootCMS奇偶數判斷(隔行變色)各種條件判斷和標籤boot