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")
        }
}
相关文章
相关标签/搜索