go里面select-case和time.Ticker的使用注意事项
来源:互联网 发布:李世宏dota2 知乎 编辑:程序博客网 时间:2024/05/16 08:46
出处:
https://studygolang.com/articles/5224
上周末参加Go技术聚会,京东的美女工程师讲到一个select-case和time.Ticker的使用注意事项(真实的应用场景是:在测试收包的顺序的时候,加了个tick就发现丢包了),觉得很有意思,记录一下。
package mainimport ( "fmt" "runtime" "time")func init() { runtime.GOMAXPROCS(runtime.NumCPU())}func main() { ch := make(chan int, 1024) go func(ch chan int) { for { val := <-ch fmt.Printf("val:%d\n", val) } }(ch) tick := time.NewTicker(1 * time.Second) for i := 0; i < 20; i++ { select { case ch <- i: case <-tick.C: fmt.Printf("%d: case <-tick.C\n", i) } time.Sleep(200 * time.Millisecond) } close(ch) tick.Stop()}
输出如下:
val:0val:1val:2val:3val:4val:56: case <-tick.Cval:7val:8val:910: case <-tick.Cval:11val:12val:13val:1415: case <-tick.Cval:16val:17val:18val:19
问题出在这个select里面:
select { case ch <- i: case <-tick.C: fmt.Printf("%d: case <-tick.C\n", i)}
当两个case条件都满足的时候,运行时系统会通过一个伪随机的算法决定哪个case将会被执行
所以当tick.C条件满足的那个循环,有某种概率造成ch<-i没有发送(虽然通道两端没有阻塞,满足发送条件)
解决方案1: 一旦tick.C随机的case被随机到,就多执行一次ch<-i (不体面,如果有多个case就不通用了)
select { case ch <- i: case <-tick.C: fmt.Printf("%d: case <-tick.C\n", i) ch <- i}
解决方案2: 将tick.C的case单独放到一个select里面,并加入一个default(保证不阻塞)
select { case ch <- i:}select { case <-tick.C: fmt.Printf("%d: case <-tick.C\n", i) default:}
两种解决方案的输出都是希望的结果:
val:0val:1val:2val:3val:45: case <-tick.Cval:5val:6val:7val:8val:910: case <-tick.Cval:10val:11val:12val:13val:1415: case <-tick.Cval:15val:16val:17val:18val:19
阅读全文
0 0
- go里面select-case和time.Ticker的使用注意事项
- go里面select-case和time.Ticker的使用注意事项
- time.After 在select-case中使用的正确姿势
- SELECT LAST_INSERT_ID() 的使用和注意事项
- SELECT LAST_INSERT_ID() 的使用和注意事项
- SELECT LAST_INSERT_ID() 的使用和注意事项
- linux里面$?的使用注意事项
- select 中使用 case when 和 replace
- J2ME的List、TextBox,Ticker和Alert
- [小结]select的使用注意事项
- 针对选择语句select case的使用!
- select中case when的使用
- C语言-Switch 和case 的使用注意事项以及穿透效果的使用
- 各个数据库的差异及使用(关于case和time functions)
- Go语言程序设计的一些规则和注意事项
- case语句在select中的用法,以及,insert和select和case合用的例子
- 使用Select的3个注意事项
- golang:使用timingwheel进行大量ticker的优化
- 【安全牛学习笔记】课时94 SQLMAP自动注入-REQUEST和SQLMAP自动注入-OPTIMIZATION
- mate 标签中属性 以及内核选择
- 网络协议与端口
- 国内开源镜像站点汇总2017年10月版
- bzoj 4429: [Nwerc2015] Elementary Math小学数学 网络流
- go里面select-case和time.Ticker的使用注意事项
- tensorflow学习day2简单监督学习模型及用tf.train.Saver实现检查点恢复
- 云计算建立标准才能给创业者公平机会
- linux系统下安装chrome
- 经验:《王者荣耀》技术总监分享背后技术
- VS2013搭建OpenGL环境
- axios 中文文档 翻译
- MergeSort分治实现代码(java)
- java下对excel文件的上传