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.

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

        go say(ch)
        select {
        case c := <-ch1:
                print(c)
        default:
                print("no answer")
        }
}

 

转载于:https://my.oschina.net/u/3470972/blog/1581810

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值