分享
  1. 首页
  2. 文章

Go语言——channel详解

陈先生_9e91 · · 1430 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Go语言——channel详解

参考:

深入理解Golang Channel

channel和goroutine是go语言最具特色是结构,有必要仔细研究。

源码路径:go1.10\src\runtime\chan.go

struct

type hchan struct {
 qcount uint // total data in the queue
 dataqsiz uint // size of the circular queue
 buf unsafe.Pointer // points to an array of dataqsiz elements
 elemsize uint16
 closed uint32
 elemtype *_type // element type
 sendx uint // send index
 recvx uint // receive index
 recvq waitq // list of recv waiters
 sendq waitq // list of send waiters
 lock mutex
}
  • qcount:当前chann元素个数,len()
  • dataqsiz:chann容量,cap()
  • buf:元素缓冲区
  • elemsize:元素大小
  • closed:close标志位
  • elemtype:元素类型
  • sendx:下一个发送元素所在缓冲区索引
  • recvx:下一个接收元素所在缓冲区索引
  • recvq:接收G的等待队列
  • sendq:发送G的等待队列

从上面可以看出,waitq非常重要

type waitq struct {
 first *sudog
 last *sudog
}
type sudog struct {
 g *g
 isSelect bool
 next *sudog
 prev *sudog
 elem unsafe.Pointer // data element (may point to stack)
 acquiretime int64
 releasetime int64
 ticket uint32
 parent *sudog // semaRoot binary tree
 waitlink *sudog // g.waiting list or semaRoot
 waittail *sudog // semaRoot
 c *hchan // channel
}

waitq是一个queue,具有头尾指针。

sudog封装了等待chann接收/发送的G。

new

chan不能直接new,只能make,所以观察makechan方法。make的时候,会根据size判断是缓冲chan还是非缓冲chan,这个逻辑需要注意。

func makechan(t *chantype, size int) *hchan {
 elem := t.elem
 // Hchan does not contain pointers interesting for GC when elements stored in buf do not contain pointers.
 // buf points into the same allocation, elemtype is persistent.
 // SudoG's are referenced from their owning thread so they can't be collected.
 // TODO(dvyukov,rlh): Rethink when collector can move allocated objects.
 var c *hchan
 switch {
 case size == 0 || elem.size == 0:
 // Queue or element size is zero.
 c = (*hchan)(mallocgc(hchanSize, nil, true))
 // Race detector uses this location for synchronization.
 c.buf = unsafe.Pointer(c)
 case elem.kind&kindNoPointers != 0:
 // Elements do not contain pointers.
 // Allocate hchan and buf in one call.
 c = (*hchan)(mallocgc(hchanSize+uintptr(size)*elem.size, nil, true))
 c.buf = add(unsafe.Pointer(c), hchanSize)
 default:
 // Elements contain pointers.
 c = new(hchan)
 c.buf = mallocgc(uintptr(size)*elem.size, elem, true)
 }
 c.elemsize = uint16(elem.size)
 c.elemtype = elem
 c.dataqsiz = uint(size)
 
 return c
}

这里看到由于要对buf对象分配,所以没有提供new方法,只能make。除了对default情况比较容易理解,另外两只buf的内存分配都不是很理解=。=,先遗留。

send & revc

send & revc

send

recv


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:陈先生_9e91

查看原文:Go语言——channel详解

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1430 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏