栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

[golang]channel源码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[golang]channel源码


简单概括:

1个数据缓存+2个协程队列

解释:
数据缓存:是一个环形队列,存放具体数据,是int还是bool还是结构体

协程队列包含发送写协程队列和读协程队列
写协程队列,:当数据缓存满时,写操作会阻塞,并放入写协程队列
读协程队列:当数据缓存空时,读操作会阻塞,并放入读协程队列.

原理就是很简单,具体结构在 runtime.hchan中

源码

当我们创建 var c = make(chan boo,2l)时

  • qcount 代表当前队列剩余元素个数.    一个没插入,因此是0
  • dataqsiz 环形队列长度, 你设置的是2,那么他就是2. 如果是无缓冲的channel,就是0
  • bvuf 环形队列指针   指向具体的缓存对象
  • elemsize 每个元素大小,int型的就是8字节  ,bool型的就是1字节 
  • sendx 写入元素位置下标.   你插入一个
  • recvx 从队列的该位置读出 
  • recvq 等待读消息的协程队列 
  • sendq 等待写消息的协程队列 
  • lock 互斥锁,不允许并发操作

写入流程:

1.有缓存则放缓存

2.缓存没位置则放sendq,等待唤醒

读取流程

1.sendq不为空,缓存不为空,先拿缓存的,再从sendq拿出一个数据,放到缓存,唤醒之前阻塞的g

2.sendq不为空,缓存为空,说明缓存长度是0, 直接取出g,拿走,唤醒.

3.sendq为空,缓存不为空,从缓存拿数据走人

4.sendq为空,缓存为空,说明没人放东西,阻塞

close流程

1.已经关闭的,再次调用会panic

2.唤醒sendq,触发panic(panic: send on closed channel),

  唤醒recvq,设置g的值为nil,用户读到的数据是类型的零值

这里有个点,别混了,如果一个channel关闭了,再去读取,会返回零值么?不是的,会看缓存数据是否为空,不为空,则返回缓存数据内容,为空,则返回零值.   上面这句话,recvq中有协程队列,一个隐含意思就是,你的缓存中已经没有数据了.

那么你可能会有疑问,你读取到了一个类型的零值,你怎么知道是close之后返回的零值,还是说就写入了一个零值?

这个问题和map一样,如果你读取map的key,返回了一个零值,你怎么知道是本身存的零值还是没有key返回的零值呢? 就是加个bool返回值呗,多告诉你点信息.

func TestOk(t *testing.T) {
	a := make(chan string, 2)
	a <- "a"
	close(a)  // ① 关闭channel
	go func() {
		d, ok := <-a
		if ok {
			fmt.Println("read data: " + d)
		}
		d2, ok := <-a
		if !ok {   // ②读取是否成功
			fmt.Println("not read data: " + d2)
		}
	}()
	time.Sleep(10 * time.Second)
}

如果没有①的代码. 即不关闭.
输出结果:
read data: a


如果有①的代码.
read data: a
not read data: 

其他: 1.channel没有初始化,去读写.会阻塞

 2.channel关闭后去写,再次关闭,会引发panic.   

panic: send on closed channe

注意:读不会,读的时候,1.如果缓存有值,则返回缓存数据 2.缓存无值,会返回零值.

3.读写channel时一定会阻塞么

有个block的参数可以控制

比如 select操作,编译时候就翻译成 not block了

4.range读取channel

规则:读取时,如果读不到,会一直阻塞.   当被close掉,会解除阻塞状态.

其实都是语法糖,你普通读,读不到也是阻塞,当close掉,先读缓存,缓存为空返回零值. 

只不过range,在close掉后,不会进入到range的业务代码里.直接跳过去.

相当于:

	for true {
			data, ok := <-a
			if ok {
				fmt.Println(data)
			} else {
				break
			}
		}
转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1036904.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号