goroutine之间的通信——channel

引入

在多线程的那篇博客中,我们可以注意点,每一段代码的最后都会有这样一段代码:

	var s string
	fmt.Scan(&s)

这段代码的含义就是等待输入,那究竟是为什么需要这一段代码呢?
如果去掉了这一段代码,在屏幕上并不会输出任何东西。
因为,这个进程(主线程)创建完两个线程之后就关闭了,同时两个刚刚创建的线程,还得队列里没有运行的线程只能和主线程一起被关闭。
那有没有什么办法使得线程在运行完之后,告诉进程(主线程)它已经运行完了,然后进程(主线程)再关闭呢?
这里就引出了Golang中,协程与协程之间的通信——channel

channel

goroutine之间通过channel来通讯,可以认为channel是一个管道或者先进先出的队列,可以从一个goroutine中向channel发送数据,在另一个goroutine中取出这个值。

定义

var 名字 chan 类型

创建

make(chan 类型,长度)

有长度的channel被称作带缓冲的channel,当然channel也可以不带缓冲,在make中省略长度这一参数。

阻塞

  • 默认情况下,channel的读与写都是阻塞的,除非另一端已经准备好了。
  • 带缓冲的channel可以不断写入,直到缓冲长度满了才阻塞。

写入(发送)

c:=chan int
c<-1

向c中写入1。

读取(接收)

c:=chan int
i:=<-c

从c中读取,并将这个数据储存到变量i。

关闭

这个并不是一个必须的操作。
如果向一个已经关闭的channel里面写入数据就会造成panic。
如果从一个已经关闭的channel里面读取信息,就会获取到相应类型的0值。
如果再次关闭一个已经关闭的channel,也会造成panic。

超时问题

如果一个协程在某一个channel阻塞太久,系统也是无法检测到的,而且channel自身也是没有定时器的,并不会因为自身阻塞太久而关闭。
而被阻塞的协程以及channel的资源是无法被回收的,最终会造成内存泄漏。
为此,我们可以写一个select来避免这种情况的发生。

func timeout() {
	time.Sleep(10000)
	chan2 <- true
}

func main() {
	chan1 = make(chan int)
	chan2 = make(chan bool)
	go timeout()
	select {
	case <-chan1:

	case <-chan2:
		fmt.Println("chan1长时间为接收到数据")
	}
}

最后通过经典的生产者消费者模型来更好地理解channel。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值