Go By Example 系列:非阻塞 Channels 操作

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

註:該系列文章全部來自 Go By Example 系列翻譯而來,個人翻譯水平以及理解水平有限,如要更加精確的理解,請看原文Go by Example: Non-Blocking Channel Operations。

在 channels (通道?) 上基本的 sends (發送) 和 receives (接收)是阻塞模式的。儘管如此, 我們可以使用 select 和一個 default 子句來非阻塞的 sends、receives,甚至是非阻塞的多路選擇。

註:感謝@lidashuang的說明提醒,文章沒有描述清楚,修改如下:select預設是阻塞的,但在select裡面還有default文法,這類似於switch,default就是當監聽的channel都沒有準備好的時候,預設執行的(select不再阻塞等待channel)
同時,有時候會出現goroutine阻塞的情況,可以利用select設定逾時來避免整個程式進入阻塞狀態

代碼版本一

代碼如下:

package mainimport "fmt"func main() {    messages := make(chan string)    signals := make(chan bool) /**這裡是一個非阻塞 receive。如果在 messages 上的值是可用的,那 select 將 <-messages 的值帶上,執行 <-messages 下面的println語句。如果不是,它將立即帶上 default 的值,執行 default 下面的println語句**/    select {    case msg := <-messages:        fmt.Println("received message", msg)    default:        fmt.Println("no message received")    }/**一個非阻塞 send 的類似工作 **/    msg := "hi"    select {    case messages <- msg:        fmt.Println("sent message", msg)    default:        fmt.Println("no message sent")    }/**我們可以用在 default 之上使用多個 cases 來實現一個非阻塞的多路 select。在這裡我們嘗試在 messages 和 signals 上實現非阻塞 receives。**/    select {    case msg := <-messages:        fmt.Println("received message", msg)    case sig := <-signals:        fmt.Println("received signal", sig)    default:        fmt.Println("no activity")    }}

最後程式的結果輸出為:

$ go run non-blocking-channel-operations.go no message receivedno message sentno activity

代碼版本二

代碼如下:

package mainimport (    "fmt")func main() {    // messages := make(chan string)    //如果不加緩衝的話,就全部會選擇defalut    messages := make(chan string, 1) //加了緩衝的話,會選擇對應的    signals := make(chan bool)    // messages <- "test"    select {    case msg := <-messages:        fmt.Println("received message", msg) //因為messages目前本身還沒有值,因此選擇default執行    default:        fmt.Println("no message received")    }    // go func() {    msg := "hi world"    // }()    select {    case messages <- msg:        fmt.Println("sent message", msg) //因為channels有緩衝,所以這裡的msg發送到 channels messages 能處理,不會被阻塞住    default:        fmt.Println("no message sent")    }    select {    case msg := <-messages:        fmt.Println("received message", msg) //因為messages已經有值了,所以會選擇這個case執行    case sig := <-signals:        fmt.Println("received signal", sig)    default:        fmt.Println("no activity")    }}

輸出結果如下:

$ go run non-blocking-channel-operations.go no message receivedsent message hi worldreceived message hi world   

代碼版本三

代碼如下:

package mainimport (    "fmt")func main() {    // messages := make(chan string)    //如果不加緩衝的話,就全部會選擇defalut    messages := make(chan string, 1) //加了緩衝的話,會選擇對應的    signals := make(chan bool)    messages <- "test"    select {    case msg := <-messages:        fmt.Println("received message", msg) //messages已經有值,因此選擇這個case執行    default:        fmt.Println("no message received")    }    // go func() {    msg := "hi world"    // }()    select {    case messages <- msg:        fmt.Println("sent message", msg)    default:        fmt.Println("no message sent")    }    select {    case msg := <-messages:        fmt.Println("received message", msg)    case sig := <-signals:        fmt.Println("received signal", sig)    default:        fmt.Println("no activity")    }}

代碼輸出結果如下:

$ go run non-blocking-channel-operations.go received message testsent message hi worldreceived message hi world

代碼版本四

代碼如下:

package mainimport (    "fmt")func main() {    messages := make(chan string) //如果不加緩衝的話,就全部會選擇defalut    //messages := make(chan string, 1) //加了緩衝的話,會選擇對應的    signals := make(chan bool)    messages <- "test" //因為該channels沒有緩衝,而其又賦值了,會到時死結。    select {    case msg := <-messages:        fmt.Println("received message", msg)    default:        fmt.Println("no message received")    }    // go func() {    msg := "hi world"    // }()    select {    case messages <- msg:        fmt.Println("sent message", msg)    default:        fmt.Println("no message sent")    }    select {    case msg := <-messages:        fmt.Println("received message", msg)    case sig := <-signals:        fmt.Println("received signal", sig)    default:        fmt.Println("no activity")    }}

代碼輸出結果為:

fatal error: all goroutines are asleep - deadlock!

runtime goroutine

runtime包中有幾個處理goroutine的函數

  1. Goexit - 退出當前執行的goroutine,但是defer函數還會繼續調用
  2. Gosched - 讓出當前goroutine的執行許可權,調度器安排其它等待的任務運行,並在下次某個時候從該位置恢複執行
  3. NumCPU - 返回CPU核心數量
  4. NumGoroutine - 返回正在執行和排隊的任務總數
  5. GOMAXPROCS - 用來設定可以啟動並執行CPU核心數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.