土拨鼠goroutine读取数据和chan的关系.

blackdinosuar · · 379 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
##文章参考:https://blog.csdn.net/guyan0319/article/details/90201405 1 goroutine之间通信go推荐使用chan的方式,chan本身是安全的有类型的 2 chan的数据结构在src/runtime/hchan中 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 protects all fields in hchan, as well as several // fields in sudogs blocked on this channel. // // Do not change another G's status while holding this lock // (in particular, do not ready a G), as this can deadlock // with stack shrinking. //锁 lock mutex } 3创建一个chan时chan的结构图. make(chan int ,3)->缓冲区为3 ![chan1.JPG](https://static.studygolang.com/190828/9f58c480e10bc305196e12869278ea3e.JPG) 数据写入到buf中,qcount=1, sendx=1,下一次存入的位置 rendx:如果buf不为空 rendx=sendx1-,如果为空=sendx 4 chan<-3时通道和roroutine的关系 4.1 写入通道时.锁住整个chan 4.2 确定写入.这时会尝试从recvq(等待读取的消息队列)中获取等待的goroutine,获取到直接赋值->gorotuine 4.3 如果recvq为空.确定缓冲区是否可用(未满),将数据写入到缓冲区 4.4 若果recvq为空.且缓冲区已满.把数据保存到当前的goroutine中(当前的goroutine就是想要写入的go).把这个goroutine加入到sendq(等待写入的队列),当前的goroutine挂起(就是阻塞 让出cpu) 4.5 写入完毕释放锁 4.6 逻辑图 ![chan3.JPG](https://static.studygolang.com/190828/fab4bf7a90f6d9e2c2304164c79f0254.JPG) 5 <-chan 读取数据chan的状态 ![chan2.JPG](https://static.studygolang.com/190828/0a10a696e087140636b31dcaf72cd24b.JPG) 读取后 ![chan4.JPG](https://static.studygolang.com/190828/ff69b9e2f3a0526c96c731a9cb8278fe.JPG) 读取后buf为空sendx和recvx都是1 5.1读取数据时.先获取chan全局锁 5.2尝试从sendq等待队列中获取等待的goroutine 5.3如果有等待的goroutine,没有缓冲区,取出goroutine的数据.然后弄醒这个goroutine,释放锁.读取结束 5.4如果有等待的goroutine,有缓冲区(缓冲区已满),从缓冲区队首取出数据(),在从sendq中取出一个goroutine,弄醒这个 goroutine(这个goroutine就是写入数据时缓冲满了休眠的go),放入到buf的队尾. 5.5如没有等待的goroutine,且缓冲区有数据,直接读取缓冲区数据,结束读取释放锁 5.6如没有等待的goroutine,且没有缓冲区或缓冲区为空,将当前的goroutine加入sendq排队,进入睡眠,等待被写goroutine唤醒。结束读取释放锁 5.7图 ![chan5.JPG](https://static.studygolang.com/190828/bc2c44b07c8885be7e14707a9081bdb5.JPG)

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

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

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