Go非阻塞channel的常見寫法

    go做爲一種自然支持併發的語言,它的併發操做特別簡單,以下:緩存

package main

func hello(word string) {
      fmt.Println("hello, ", word)
}

func main() {
      word := "world"
      go hello(word)
      fmt.Println(word)
}

直接在須要併發的語句前加上關鍵字go便可,深刻了解一下go關鍵字背後實際上是執行了一個runtime.newproc()方法新生成一個goroutine來執行接下來的語句。那既然是生成了一個子協程,在平常編碼的過程當中,就確定會涉及到如何在主協程和子協程之間進行通訊的問題。通常地,在go的多線程環境中,咱們一般使用go的管道類型channel來實現通訊,當數據在channel中時,同一時刻只有一個協程可以訪問數據,避免了出現競爭的可能,從而保證了併發安全。安全

    可是channel默認是一種阻塞類型,若是編碼的時候不注意代碼的順序,常常會致使程序出現死鎖的狀況。以下代碼就華麗麗的遇到了死鎖:多線程

func say(ch chan int) {
        ch <- 2
}

func main() {
        ch := make(chan int)
        say(ch)                                                                                                                                                                                                                                                
        print(<-ch)
}

那應該如何實現非阻塞的channel使用:併發

1. 使用go關鍵字,建立一個新的協程,讓管道的push和pop不在同一個協程中執行就能夠避免死鎖。編碼

func main() {
        ch := make(chan int)
        go say(ch)                                                                                                                                                                                                                                             
        print(<-ch)
}

2. 使用有緩存的管道channel,初始化時給channel指定buffer大小,在管道內的數據小於等於buffer值時,不會阻塞;超過則阻塞;線程

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

3. 使用select關鍵字,該關鍵字能夠監控channel管道中的數據流動,有流動就會觸發相應的case,沒有流動select會一直阻塞,相似於switch.code

func main() {
        ch := make(chan int)
        ch1 := make(chan int)                                                                                                                                                                                                                                  

        go say(ch)
        select {
        case c := <-ch1:
                print(c)
        default:
                print("no answer")
        }
}
相關文章
相關標籤/搜索