從Deadlock報錯理解Go_channel機制(二)

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

上一篇主要討論了無緩衝通道遭遇死結的幾種情況,這篇文章我們繼續討論通道的另一種類型——緩衝通道(buffered channel)。

基本性質

緩衝通道顧名思義,就是帶有緩衝區(buffered)的通道。緩衝區作為資料的臨時儲存地區,可以作為資料的臨時存放空間。初始化如下:

var ch = make(chan int, 1)

make的第二個參數代表緩衝區的長度,也就是說,通道ch在接收到第一個訊息的時候不會掛起,它會把訊息存到緩衝區中等待接收的goroutine將其提走。如果此時未提走而新的訊息到達,通道將會阻塞並掛起。

更詳細地舉個例子:

func main() {    ch := make(chan int, 3)    ch <- 1    ch <- 2    ch <- 3}

在這段代碼中,通道ch可以緩衝三個資料,在流入一個資料main函數將掛起並返回死結錯誤。

緩衝通道和無緩衝通道的一個區別在於,在沒有滿容量的時候,緩衝通道可以在同一個goroutine中完成資料的傳輸和提取:

import "fmt"func main() {    ch := make(chan int, 3)    ch <- 1    ch <- 2    ch <- 3    fmt.Println(<-ch)    fmt.Println(<-ch)    fmt.Println(<-ch)}

結合前文提到通道的隊列屬性,這帶來的好處是,在未滿容量的情況下,緩衝通道可以作為安全執行緒的隊列使用。

通道訊息的讀模數式

接收通道資料的方式除了一個一個讀取(如上範例程式碼)之外,Go還提供了range關鍵字:

import "fmt"func main() {    ch := make(chan int, 3)    ch <- 1    ch <- 2    ch <- 3    // close(ch)    for value := range ch {        fmt.Println(value)    }}

然而上述代碼在執行完畢後會報deadlock的錯誤,其原因在於range不會自動檢測通道是否乾涸(drained),在提取完全部資料後,再次提取會使main函數掛起。解決方案也有兩個,第一個是在for迴圈中設定長度檢測,如果通道buffer為空白則跳出迴圈;第二種是在接受完全部資料後關閉通道。這裡值得注意的一點是,關閉狀態的通道永遠不會阻塞。

第二種方法揭示了通道的另一個特性:對於關閉的通道無法再接收新的資料,但是可以嘗試提取其中存留的資料。

容量為1的緩衝通道

根據通道的特性我們不難發現,如果將通道容量設定為1,我們可以利用它作為訊號量(semaphore)來保護共用變數(shared variable)的安全執行緒。

// gop1.io/ch9/bank2var (    sema = make(chan struct{}, 1)    balance int)func Deposit(amount int) {    sema <- struct{} // acquire token    balance = balance + amount    <- sema // release token}func Balance() int {    sema <- struct{} // acquire token    b := balance    <-sema // release token    return b}

這種為共用變數加的鎖我們稱之為二元訊號量(binary semaphore)。由於二元訊號量十分有用,Go甚至提供了專門的sync庫協助我們更方便地使用鎖。上述代碼可以改寫如下:

import "sync"var (    mu sync.Mutex // guards balance    balance int)func Deposit(amount int) {    mu.Lock()    balance = balance + amount    mu.Unlock()}func Balance() int {    mu.Lock()    defer mu.Unlock()    // maybe more operations here    return balance}

Balance函數中我們利用defer防止因error或者panic導致鎖未解除。

Reference: Donovan, Alan AA, and Brian W. Kernighan. The Go programming language. Addison-Wesley Professional, 2015.

--

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.