Golang的chan阻塞测试
在《The way to go - 14.2 协程间的信道》教程中看到了关于chan阻塞的相关内容,自己写代码对通道的阻塞特性做了一点测试。
贴之前先复习一下知识点。以下是我自己的总结,如果不对还请网友指正。
1,golang的通道(chan)可分为不带缓存的通道和带缓存的通道。用make函数创建通道的时候,如果不指定缓存大小,创建的就是不带缓存的通道。
2,通道是一个类型化消息队列。这句话有两个意思,一是在创建通道时,需要指定通道中传输什么类型的数据。例如var c chan int,这句代码声明了一个名字叫c的通道,这个通道只能传输int类型的数据。int也可以换成空接口(interface{})类型,但数据接收端在使用数据时就需要进行数据类型判定。这句话的第二个意思是通道是一个先进先出(FIFO)的结构,放入通道的数据具有时序性。
3,向通道中放入数据的一端可以称为生产者,从通道获取数据的一端可以称为消费者。
c := make(chan int) // 不带缓存的通道
c <- 100 // 生产
recv := <- c // 消费
4,不带缓存的通道,在通道任一一端没有准备就绪之前,另一端就会产生阻塞。下面用The way to go的例子来说明。
package mainimport ("fmt"
)func f1(in chan int) {fmt.Println(<-in)
}func main() {out := make(chan int)out <- 2go f1(out)
}
上面这段代码在执行的时候会产生死锁。在main函数中先执行向out通道中放入数据,再启动go协程。在向out通道放入数据时,通道的消费者还未准备就绪(粗暴一点解释就是,还没有执行到消费数据的代码),所以程序会一直在out <- 2这个地方一直阻塞,不会执行go f1(out)。不执行go f1(out)的结果就是,go协程中的消费者端就永远不会就绪。这段代码只需要将启动go协程和向通道放入数据的代码前后调换下位置,就可以解决死锁。
接下来就用两个稍微复杂一点的程序来说明通道阻塞。
例1:
func main() {// 创建不带缓存的通道c := make(chan int)// 启动go协程并将通道c作为参数传入go myRoutine(c)// 向通道中写入数据,并在写入成功后打印写入成功的消息for i := 0; i < 10; i++ {c <- ifmt.Printf("Sent %v to chan\n", i)}// 打印程序结束时间fmt.Printf("End process at %v", time.Now())
}func myRoutine(c chan int) {// 打印go协程启动时间fmt.Printf("Start goroutine at %v\n", time.Now())var msg intfor {time.Sleep(4 * 1e9)// 从通道中接收数据msg = <-ctime.Sleep(1 * 1e9)// 打印接收到的数据和接收时间fmt.Printf("Get msg %d from chan at %v\n", msg, time.Now())}
}
程序输出如下:
Start goroutine at 2021-10-01 10:41:45.9047405 +0800 CST m=+0.002146401
Sent 0 to chan at main method.
Get msg 0 from chan at 2021-10-01 10:41:50.918935 +0800 CST m=+5.016340901
Sent 1 to chan at main method.
Get msg 1 from chan at 2021-10-01 10:41:55.9351083 +0800 CST m=+10.032514201
Sent 2 to chan at main method.
Get msg 2 from chan at 2021-10-01 10:42:00.9482089 +0800 CST m=+15.045614801
Sent 3 to chan at main method.
Get msg 3 from chan at 2021-10-01 10:42:05.9627741 +0800 CST m=+20.060180001
Sent 4 to chan at main method.
Get msg 4 from chan at 2021-10-01 10:42:10.9670808 +0800 CST m=+25.064486701
Sent 5 to chan at main method.
Get msg 5 from chan at 2021-10-01 10:42:15.9917451 +0800 CST m=+30.089151001
Sent 6 to chan at main method.
Get msg 6 from chan at 2021-10-01 10:42:21.0252843 +0800 CST m=+35.122690201
Sent 7 to chan at main method.
Get msg 7 from chan at 2021-10-01 10:42:26.0522605 +0800 CST m=+40.149666401
Sent 8 to chan at main method.
Get msg 8 from chan at 2021-10-01 10:42:31.0667841 +0800 CST m=+45.164190001
Sent 9 to chan at main method.
End process at 2021-10-01 10:42:35.0850043 +0800 CST m=+49.182410201
从上面的输出可以看出在执行到msg = <-c这句代码之前(消费者端就绪之前),生产者端是处于发送等待状态(阻塞)的。消费者端一旦准备就绪,生产者端马上向通道中写入数据。
例2:
func main() {c := make(chan int)go myRoutine(c)time.Sleep(5 * 1e9)for i := 0; i < 5; i++ {c <- ifmt.Printf("Sent %v to chan at main method.\n", i)time.Sleep(5 * 1e9)}fmt.Printf("End process at %v", time.Now())
}func myRoutine(c chan int) {fmt.Printf("Start goroutine at %v\n", time.Now())var msg intfor {fmt.Printf("Ready to get msg from chan at %v\n", time.Now())msg = <-cfmt.Printf("Get msg %d from chan at %v\n", msg, time.Now())}
}
程序输出如下:
Start goroutine at 2021-10-01 10:55:51.5484438 +0800 CST m=+0.002574401
Ready to get msg from chan at 2021-10-01 10:55:51.5609746 +0800 CST m=+0.015105201
Sent 0 to chan at main method.
Get msg 0 from chan at 2021-10-01 10:55:56.5649773 +0800 CST m=+5.019107901
Ready to get msg from chan at 2021-10-01 10:55:56.5649773 +0800 CST m=+5.019107901
Sent 1 to chan at main method.
Get msg 1 from chan at 2021-10-01 10:56:01.5794729 +0800 CST m=+10.033603501
Ready to get msg from chan at 2021-10-01 10:56:01.5794729 +0800 CST m=+10.033603501
Sent 2 to chan at main method.
Get msg 2 from chan at 2021-10-01 10:56:06.5900095 +0800 CST m=+15.044140101
Ready to get msg from chan at 2021-10-01 10:56:06.5900095 +0800 CST m=+15.044140101
Sent 3 to chan at main method.
Get msg 3 from chan at 2021-10-01 10:56:11.6087279 +0800 CST m=+20.062858501
Ready to get msg from chan at 2021-10-01 10:56:11.6087279 +0800 CST m=+20.062858501
Sent 4 to chan at main method.
Get msg 4 from chan at 2021-10-01 10:56:16.6128717 +0800 CST m=+25.067002301
Ready to get msg from chan at 2021-10-01 10:56:16.6128717 +0800 CST m=+25.067002301
End process at 2021-10-01 10:56:21.6246286 +0800 CST m=+30.078759201
从上面的输出可以看出在执行到main函数中c <- i这句代码之前(生产者端就绪之前),消费者端是处于发送等待状态(阻塞)的。生产者端一旦准备就绪,消费者端马上从通道中取得数据,并开始执行之后的打印语句。
Golang的chan阻塞测试相关推荐
- 制坯系列-Golang专题-chan
<制坯系列-Golang专题>:chan作为协程之间通信的重要方式,是替代内存共享的最佳通信方式,本文对基本原理和关键知识点做简单介绍 chan底层数据结构 type hchan stru ...
- golang 学习 - chan以及chan的一下用例
golang 学习 - chan 1. 通道 // _通道_ 是连接多个 Go 协程的管道.你可以从一个 Go 协程 // 将值发送到通道,然后在别的 Go 协程中接收.package mainimp ...
- golang的chan(管道)
golang的chan翻译成中文就是管道,顾名思义,就是管道的一端用来读,另一端用来写,这与write和read函数的性质是非常相似的,比如说管道中没数据,就会发生读阻塞,管道中数据是满的,就会发生写 ...
- GoLang之go test测试
文章目录 GoLang之go test测试 1.介绍 2.函数 3.测试函数格式 3.1格式 3.2失败示例 3.3成功示例1 3.4成功示例2 3.5成功示例3 3.6成功实例4 4.基准函数 4. ...
- go/golang语言编写压力测试
go/golang语言编写压力测试 近期复习了一下go,发现go的压力测试是个好东西.记录一下怎么使用. 压力测试用来检测函数(方法)的性能,和编写单元功能测试的方法类似,此处不再赘述,但需要注意以下 ...
- golang笔记09--go语言测试与性能调优
golang笔记09--go语言测试与性能调优 1 介绍 2 测试与性能调优 2.1 测试介绍 2.2 代码覆盖率和性能测试 2.3 使用pprof进行性能调优 2.4 测试http服务器(上) 2. ...
- golang mysql 非阻塞_Golang 实现轻量、快速的基于 Reactor 模式的非阻塞 TCP 网络库...
gev 轻量.快速的 Golang 网络库 gev 是一个轻量.快速的基于 Reactor 模式的非阻塞 TCP 网络库,底层并不使用 golang net 库,而是使用 epoll 和 kqueue ...
- golang管道chan
package mainimport ("fmt""time" )func main() {//test2()test4()time.Sleep(time.Se ...
- golang基础-chan的select操作、定时器操作、超时控制、goroutine中使用recover
chan的只读和只写 a.只读chan的声明 Var 变量的名字 <-chan int Var readChan <- chan int b. 只写chan的声明 Var 变量的名字 ch ...
- Golang实践录:测试框架
这篇集中记录一下测试相关的内容. 背景 创建工程库代码,方便重用.重用方式可使用函数,也可直接引用文件. 完成函数,可在 main 函数中调用进行测试.也可以使用 test 框架进行. 在大型项目中, ...
最新文章
- java8 wordcount_Spark2.x与Java8下WordCount示例
- R语言使用ggplot2包使用geom_violin函数绘制分组小提琴图(配置填充色调色板、brewer调色板、灰度比例)实战
- spring boot模板引擎thymleaf用法详解
- vuecli4 启动_vue 常见命令 (启动 部署)
- 少儿计算机兴趣小组活动记录,2013年度儿童画兴趣小组活动记录Word编辑
- jq的插件 vue中引用_详解如何在 vue 项目里正确地引用 jquery 和 jquery-ui的插件
- Tomcat启动报Error listenerStart错误
- 卢伟冰:这几天黑稿明显增多了 法务又要忙了
- 清退117名博士、119名硕士!研究生“严出”成人才培养大趋势
- dat关闭某进程_电脑程序卡住怎么办?结束进程只需要这三个键
- 基于DSP的主动降噪开发之三(CCS软件学习)
- ios13短信如何转移到android,iOS13加入全新数据迁移功能,无需网络也能转移旧手机数据...
- python开发指法练习软件_猿编程电脑端
- UML一篇文章就学通!
- 【quartus】packed unpacked array
- oracle通信通道的文件结尾_“ORA-03113: 通信通道的文件结尾”报错处理
- 计算机桌面按哪个键锁定呀,计算机锁定屏幕快捷键-一种锁定计算机屏幕的快捷方式...
- 高级语言程序设计(实验四)
- 数据结构与算法基础——重要知识点截图【青岛大学-王卓版】
- AVPlayer使用学习
热门文章
- 街景影像分析入门(二)无需秘钥,抓取百度街景影像
- kill word out e ef en em
- 用友U8 业务单据打印机设置
- 解决“error C1083: 无法打开包括文件: “HPSocket.h”: No such file or directory”
- 腾讯战华为:一场「渠道」之争背后,游戏行业变天了
- 支付宝登陆泰国最大免税店King Power可扫码支付
- wed基础和http
- iphone个系列尺寸_iPhone9只是套模iPhone8,这些才是iPhone经典款,你用过哪些?
- hdu5294Tricks Device【最短路+网络流】
- ASP.NET Core 自定义中间件