首先编程的时候遇到疑问,输出跟我所想预想不一样,后来查到了golang社区的帖子,其中一篇帖子 :健哥大人  做出了一些解释。

我摘抄重点过来:

无缓冲的与有缓冲channel有着重大差别,那就是一个是同步的 一个是非同步的。

比如

c1:=make(chan int)         无缓冲

c2:=make(chan int,1)      有缓冲

c1<-1                            

无缓冲: 不仅仅是向 c1 通道放 1,而是一直要等有别的携程 <-c1 接手了这个参数,那么c1<-1才会继续下去,要不然就一直阻塞着。

有缓冲: c2<-1 则不会阻塞,因为缓冲大小是1(其实是缓冲大小为0),只有当放第二个值的时候,第一个还没被人拿走,这时候才会阻塞。

我对以上做一些解释,首先确实得承认channel有缓存与无缓存确实差别巨大,缓存为1和不设置缓存输出有差别。但是上面有缓存的解释是合理的,无缓存的我保留一下意见,用用代码实例来做下分析。

首先看示例1:

package main import ( "fmt" ) func main() { jobs := make(chan int, 1) done := make(chan bool) go func() { // fmt.Println("GoStart") for i := 1; ; i++ { // fmt.Println("GoforSTART", i) j, more := <-jobs if more { fmt.Println("received job", j) } else { fmt.Println("received all jobs") done <- true return } // fmt.Println("GoforEND", i) } }() for j := 1; j <= 3; j++ { // fmt.Println("OutFOR", j) jobs <- j fmt.Println("sent job", j) } close(jobs) fmt.Println("sent all jobs") <-done }

其输出是:

sent job 1
received job 1
sent job 2
received job 2
sent job 3
sent all jobs
received job 3
received all jobs

这是有缓存的情况,输出跟大家所预想的是一样的,每次遇到

jobs <- j

程序会继续向下执行,直到程序循环到下次 jobs <- j,因为jobs的开辟的缓存已满,故程序转而执行goroutine部分,在goroutine中,当程序执行至

j, more := <-jobs

取出channel中的值,等到goroutine中遇到阻塞,回到外部main()函数继续执行

然后分析看示例2:

将上一段得程序有缓存channel修改为无缓存,即:

jobs := make(chan int, 1)

修改为

jobs := make(chan int)

并将代码中的注释部分全部还原执行。

其输出是:

OutFOR 1
GoStart
GoforSTART 1
received job 1
GoforEND 1
GoforSTART 2
sent job 1
OutFOR 2
sent job 2
OutFOR 3
received job 2
GoforEND 2
GoforSTART 3
received job 3
GoforEND 3
GoforSTART 4
sent job 3
sent all jobs
received all jobs

我们分析:

当for循环运行至第一次 jobs <- j ,程序直接进入goroutine,由输出的“ GoStart” 紧跟 “OutFOR 1” 得到验证。然后程序执行至在goroutine中for的第二次循环

j, more := <-jobs

处阻塞,回到外部main()的for循环。

但外部main的for循环执行第二圈时,并未在 jobs <- j  后进入goroutine,而是继续执行,由

sent job 2
OutFOR 3

紧跟

OutFOR 2

得到验证。

而外部for进入第三次循环时阻塞,因为jobs中得值还未取出,故而转入goroutine继续执行。

问题出在

jobs <- j

是继续执行还是阻塞去在其他goroutine中传递值,按照本文开头索引的帖子所指出,应该jobs 通道放j,需要有携程接手这个参数,才可继续执行,但上面得分析看到情况并非如此。

示例3:

package mainimport ("fmt"
)func main() {jobs := make(chan int)go func() {fmt.Println("Goroutin Start")for {select {case src := <-jobs:fmt.Println("Get ", src)}}}()for j := 0; j < 5; j++ {jobs <- jfmt.Println("Sent job ", j)}close(jobs)fmt.Println("finish.")
}

其输出为:

Goroutin Start
Get  0
Sent job  0
Sent job  1
Get  1
Get  2
Sent job  2
Sent job  3
Get  3
Get  4
Sent job  4
finish.

当遇到向channel写入值,是否往下执行是交替的,也就是说是随机的。

本文示例环境是go 1.4,本文所做的解释也是因为携程都是利用同一cpu在不同时间片上运行所做的输出分析。

goroutine利用阻塞同步携程之间的数据是非常重要的思想,但大家编程的时候要特别小心。

golang的Channel初始化的有缓存与无缓存解释相关推荐

  1. 全缓存、行缓存和无缓存

    在标准I/O中,核心对象是流.所谓流,它是一个过程,所有的I/O操作都是简单的从程序的移进或移出,我们把这种字符流叫做流.标准I/O基于流的操作都是缓存文件系统. 缓存类型分为三种,分别是全缓存.行缓 ...

  2. 缓存(一)——浏览器缓存

    浏览器缓存 一.概述 二.工作流程 三.缓存示例 四.几个控制缓存策略的响应头 强缓存 协商缓存 五.实例 一.概述 浏览器缓存即http缓存,将数据缓存在浏览器(即客户端). 服务端通过设置HTTP ...

  3. golang 中 channel 的详细使用、使用注意事项及死锁分析

    什么是 channel 管道 它是一个数据管道,可以往里面写数据,从里面读数据. channel 是 goroutine 之间数据通信桥梁,而且是线程安全的. channel 遵循先进先出原则. 写入 ...

  4. golang中channel使用

    1 golang中channel使用 文章目录 1 golang中channel使用 1.1 channel介绍 1.2 channel使用 1.2.1 channel声明和初始化 1.2.2 cha ...

  5. 深入了解golang 的channel

    文章目录 1.channel 是什么 channel的特点 2.channel 的数据结构 hchan 等待队列和发送队列的类型包装 sudog 3.channel 分类 有缓冲channel 无缓冲 ...

  6. golang的channel实现原理

    golang的channel实现原理 chan结构 src/runtime/chan.go type hchan struct {qcount uint // 当前队列中剩余元素个数dataqsiz ...

  7. GoLang之channel底层的数据结构是什么、channel的创建(2)

    文章目录 GoLang之channel底层的数据结构是什么.channel的创建(2) 1.数据结构 2.创建 GoLang之channel底层的数据结构是什么.channel的创建(2) 1.数据结 ...

  8. golang中Channel通道(二)

    golang中Channel通道(二) 一.带缓冲和不带缓冲的通道的区别 1.非缓冲通道 一次发送操作对应一次接收操作,对于一个goroutine来讲,它的一次发送,在另一个goroutine接收之前 ...

  9. GoLang之channel 在什么情况下会引起资源泄漏(10)

    文章目录 GoLang之channel 在什么情况下会引起资源泄漏(10) GoLang之channel 在什么情况下会引起资源泄漏(10) Channel 可能会引发 goroutine 泄漏. 泄 ...

最新文章

  1. 衡阳之后,重估自动驾驶落地
  2. POJ1548最小路径覆盖
  3. 你一定不能错过的pandas 1.0.0四大新特性
  4. shiro学习(2):第一个shiro程序
  5. java变量命名规则_浅谈JAVA开发规范与开发细节(上)
  6. MYSQL 时间处理
  7. [bzoj 1398] Vijos1382寻找主人 Necklace 解题报告(最小表示法)
  8. pyqt:使用qrc文件配置图片资源,生成py文件
  9. NOIP模拟赛20191024 T1 嘟嘟噜【约瑟夫问题的mlogn解法】
  10. Virtuoso Layout 系列教程:01 软件安装教程 - 附资源包
  11. K8S(二)安装配置篇
  12. centOS最全下载地址
  13. Mac 格式化TF卡,获取原来的容量大小。
  14. uniapp 图片上传 删除
  15. 网易云音乐用户微观洞察精细化运营
  16. @Select注解动态sql语句
  17. 呵呵呵切克闹,Mysql优化来一套。
  18. vue入门(一)----工程vue_sell
  19. 教你win10电脑声音太小怎么办
  20. bizhubc226说明书_bizhubc226打印机如何扫描?

热门文章

  1. pulsar 卸载数据到aws-s3
  2. vue——懒加载(异步延迟和彻底懒加载)
  3. rocketmq常用命令
  4. 登录与注册 艺术与业务 的结合
  5. 结对编程 贪吃蛇项目-开发环境搭建过程
  6. 小博老师演示常用JQuery效果 ——图片轮播
  7. MyBatis学习总结(13)——Mybatis查询之resultMap和resultType区别
  8. Mac 快速修改 hosts 文件
  9. Wolf QOS 教程
  10. 机器与人交流的五大法则