Go非阻塞channel的常见写法


声明:本文转载自https://my.oschina.net/u/3470972/blog/1581810,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

    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")         } }

 

本文发表于2017年11月30日 00:33
(c)注:本文转载自https://my.oschina.net/u/3470972/blog/1581810,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2406 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1