博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Golang 入门笔记 - Channel
阅读量:2291 次
发布时间:2019-05-09

本文共 2407 字,大约阅读时间需要 8 分钟。

点击上方蓝色“Golang来啦”关注我哟

加个“星标”,天天 15 分钟,掌握 Go 语言

via:

https://medium.com/technofunnel/understanding-goroutine-go-channels-in-detail-9c5a28f08e0d
作者:Mayank Gupta
四哥水平有限,如有翻译或理解错误,烦请帮忙指出,感谢!

这篇文章源自 Medium,文章点赞 600+。

这篇文章的内容很简洁,知识点容易理解,很佩服作者能把知识点讲的通俗易懂,可能这就是文章获得高点赞的原因吧。

原文如下:


Go 语言使用 goroutine 可以轻松地实现并发。大家应该都知道,goroutine 是通过 channel 实现相互通信的。channel 确保 goroutine 和主线程时间可以相互通信。

在这篇文章中,将会与大家讨论如何创建 channel 和实现数据共享。

简单介绍下 channel

channel 给编程带来了很大的灵活性,并解决了涉及并发的各种问题。总结有如下几点:

  1. 是一种通信机制;

  2. channel 可以作为参数发送给不同的 goroutine;

  3. 既可充当发布者又可充当订阅者;

内存隔离

以前,程序通过全局变量的方式实现线程之间共享数据,我们不得不跟踪不同线程对数据的操作。

全局共享内存会导致与不同线程之间同步数据有关的诸多问题。

Go 语言通过 channel 实现了安全的数据通信,只有一个子线程可以对数据进行操作。channel 里的有效数据只能被单个 goroutine 访问。数据的接收方和发送方是一对一的关系。

第一步:创建 channel

package mainimport "fmt"func main() {  dataChannel := make(chan string)  fmt.Println(<-dataChannel)}

我们来看下上面代码值得关注的几个细节:

  1. 使用 make 关键字创建新的对象;

  2. 需要指定使用 chan 创建的对象类型;

  3. 使用 string 指定 channel 返回的数据类型;

所以第 5 行代码,我们创建了 channel 类型的对象,goroutine 之间可以用来传递 string 类型的数据。

等待获取 channel 的数据

上面第 6 行代码,main 函数会一直等待,直到从 channel 接收到数据为止。上面的代码,没任何其他 goroutine 向 channel 发送数据,程序会在等待接收数据过程发生死锁。

我们看下输出:

从运行结果可以看出,程序发生了死锁,因为 main 函数在一直等待 channel 返回数据。

第二步:往 channel 添加数据

上面的代码中,我们创建了 channel,并等待 channel 返回可用数据。由于未返回数据,程序发生死锁。

下一步,我们将在 main() 函数里为 channel 提供数据,一起来看下下面的代码:

package mainimport "fmt"func main() {  dataChannel := make(chan string)  dataChannel <- "Some Sample Data"  fmt.Println(<-dataChannel)}

上面的代码中,往 channel 添加了一些简单的数据,现在你是不是认为可以从 channel 接收到数据呢?

一起来看下输出:

从上面的输出可以看出,程序再次发生死锁。你能想出为什么吗?

上面的代码中,我们往 channel 添加数据。一旦往 channel 发送数据,主协程便发生阻塞直到有其他协程将数据从 channel 取出。由于没有其他协程将数据取出,主协程便一直阻塞,进而导致死锁。

第三步:解决死锁

需要重申一点,默认情况下,channel 是不带缓存的,这意味着数据需要被接收者立即取出,发送者协程才能继续正常工作。

如果没有协程接收数据,发送者协程将会一直阻塞。

通过带缓存区的 channel,我们可以在 channel 里存储数据,只要缓存没满,即使数据没被取出,发送者协程也可以正常工作。

我们可以使用带缓存的 channel 解决上述问题。

创建带缓存的 channel

为了保证即使在数据没被其他协程接收的情况下,发送者协程仍能正常工作,可以使用带缓存的 channel。

我们一起来看下例子:

package mainimport "fmt"func main() {  dataChannel := make(chan string, 3)  dataChannel <- "Some Sample Data"  dataChannel <- "Some Other Sample Data"  dataChannel <- "Buffered Channel"  fmt.Println(<-dataChannel)  fmt.Println(<-dataChannel)  fmt.Println(<-dataChannel)}

上面的代码,我们创建了缓存容量为 3 的 channel,意味着该 channel 可以存储 3 个 string 值。往 channel 添加的数据可以不用立即处理,直到缓存满之前,我们可以一直往 channel 添加数据。

一旦缓存满了,我们就必须处理数据否则也会发生死锁。

因此,使用带缓存的 channel,允许协程将数据保存在 channel 中,以便在后续程序执行过程中取出,从而消除死锁。

让我们看下面的输出:

从输出结果可以看出,死锁已经消除了。

推荐阅读:

如果我的文章对你有所帮助,点赞、转发都是一种支持!

给个[在看],是对四哥最大的支持

转载地址:http://byfnb.baihongyu.com/

你可能感兴趣的文章
18级大数据专家,漫谈大数据平台安全风险与建设,值得学(下篇)
查看>>
阿里P8终于整理出:Nginx+jvm+MySQL+Docker+Spring实战技术文档
查看>>
腾讯T4专家精心整理:大数据+机器学习+数据挖掘+算法大集结
查看>>
阿里P8终于总结出:SpringBoot+Tomcat+Nginx+Netty面试题及答案
查看>>
阿里P7大牛,深入剖析JVM底层设计原理+高级特性pdf,附46页ppt
查看>>
史上最全141道大数据面试题:Redis+Linux+kafka+Hadoop,附答案
查看>>
一文带你深入理解JVM,看完之后你还敢说你懂JVM吗?颠覆you认知
查看>>
这些大厂面试真题你能答出来,年薪至少30-50W,想不想挑战一下?
查看>>
携程T7用637页PDF,解读十余热门技术领域,八场携程技术沙龙干货
查看>>
开发框架SpringBoot:构建SpringBoot工程+配置文件详解+Actuator
查看>>
6年拉力工作经验,学了阿里P8级架构师的7+1+1落地项目,跳槽阿里年薪直接40W+
查看>>
90天吃透阿里P8推荐的625页Java编程兵书技术实战,直接入职阿里定级P6
查看>>
清华毕业扫地僧,用157集终于把java给讲完了,总计3.13GB
查看>>
清华毕业大佬用了一个项目就把SpringMVC+Spring+MyBatis给讲完了
查看>>
终于学完阿里P8架构师多年实战经验总结分享微服务之道实战文档
查看>>
年薪120W的架构师简历你见过吗?java程序员该如何达到?
查看>>
超赞!80W美团架构师7年心血终成轻量级框架SSM整合开发实战文档
查看>>
超赞!终于学完了阿里P8架构师7年心血整理总结的微服务实战文档
查看>>
真666!阿里资深架构师熬夜纯手写的238页微服务容器化开发实战笔记
查看>>
Mygod!阿里P8架构师20年经验总结成微服务设计企业架构转型之道笔记
查看>>