真实的应用场景是:在测试收包的顺序的时候,加了个 tick 就发现丢包了

那么来看一个应用例子:

package main

import (
"fmt"
"runtime"
"time"
) func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
} func main() {
ch := make(chan int, )
go func(ch chan int) {
for {
val := <-ch
fmt.Printf("val:%d\n", val)
}
}(ch) tick := time.NewTicker( * time.Second)
for i := ; i < ; i++ {
select {
case ch <- i:
case <-tick.C:
fmt.Printf("%d: case <-tick.C\n", i)
} time.Sleep( * time.Millisecond)
}
close(ch)
tick.Stop()
}

输出结果如下:

val:0
val:1
val:2
val:3
val:4
val:5
6: case <-tick.C
val:7
val:8
val:9
10: case <-tick.C
val:11
val:12
val:13
val:14
15: case <-tick.C
val:16
val:17
val:18
val:19

问题出在这个select里面:

select {
case ch <- i:
case <-tick.C:
  fmt.Printf("%d: case <-tick.C\n", i)
}

  [tick.C 介绍说明]当两个 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:
val:
val:
val:
val:
: case <-tick.C
val:
val:
val:
val:
val:
: case <-tick.C
val:
val:
val:
val:
val:
: case <-tick.C
val:
val:
val:
val:
val:

最新文章

  1. 软件工程导论-目录-K-T+RJ大
  2. Mybatis框架基于注解的方式,实对数据现增删改查
  3. DBUTIL 调用存储过程例子
  4. a标签不跳转
  5. Swift数据类型简介(二)
  6. 向Windows 日志管理器写入系统程序日志信息
  7. 【剑指offer】和为定值的连续正数序列
  8. SQLite存储区的日志模式
  9. mysql语句优化总结(一)
  10. php错误 分析
  11. 【leetcode】经典算法题-Counting Bits
  12. Qt窗口定制
  13. c/c++ 拷贝控制 构造函数的问题
  14. P2146 [NOI2015]软件包管理器
  15. HDU5293 : Tree chain problem
  16. Jquery闪烁提示特效
  17. Spring MVC 源码分析
  18. Redis进阶之redis的生命周期
  19. windows下安装python3 新手上路
  20. PyQt5--MenuBar

热门文章

  1. map的运用
  2. 第二阶段每日站立会议First Day
  3. Task 9 从用户界面和体验分析“360极速浏览器”
  4. 《Spring1之第三次站立会议》
  5. 抽奖系统 random()
  6. mysql中enum类型
  7. Linux进程调度策略的发展和演变(转)
  8. mysql 添加行号
  9. 第211天:git和github的区别和使用详解
  10. POJ1637_Sightseeing tour