Go channel实现源码分析
go通道基于go的并发调度实现,本身并不复杂,go并发调度请看我的这篇文章:go并发调度原理学习
type hchan struct {
qcount uint // 缓冲区中已有元素个数
dataqsiz uint //循环队列容量大小
buf unsafe.Pointer // 缓冲区指针
elemsize uint16 //元素大小
closed uint32 //关闭标记,0没关闭,1关闭
elemtype *_type //数据项类型
sendx uint //发送索引
recvx uint //接收索引
recvq waitq //等待接收排队链表
sendq waitq //等待发送排队链表
lock mutex //锁
}
type waitq struct {
first *sudog
last *sudog
}
func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
lock(&c.lock)
if c.closed != {
unlock(&c.lock)
panic(plainError("send on closed channel"))
}
if sg := c.recvq.dequeue(); sg != nil {
//缓冲区就是一个固定长度的循环列表
//发送队列是一个双向链表,接在缓冲区的后面,整体是一个队列,保证先进先出
//有接收者,并不是将当前要发送的数据直接发出,而是将缓冲区的第一个元素发送给接收者,同时将发送队列的第一个元素加入缓冲区刚出队列的位置
send(c, sg, ep, func() { unlock(&c.lock) }, )
return true
}
if c.qcount < c.dataqsiz {
//缓冲区没有满,直接将要发送的数据复制到缓冲区,直接返回,
qp := chanbuf(c, c.sendx)
typedmemmove(c.elemtype, qp, ep)
c.sendx++
if c.sendx == c.dataqsiz {
c.sendx =
}
c.qcount++
unlock(&c.lock)
return true
}
if !block {
unlock(&c.lock)
return false
}
//以上都是同步非阻塞的,ch <- 100直接返回
//以下是同步阻塞
//缓冲区满了,也没有接收者,通道将被阻塞,其实就是不执行当前G了,将状态改成等待状态
gp := getg()
mysg := acquireSudog()
c.sendq.enqueue(mysg)
goparkunlock(&c.lock, "chan send", traceEvGoBlockSend, )
//当G被唤醒,状态改成可执行状态,从这里开始继续执行
releaseSudog(mysg)
return true
}
func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool) {
lock(&c.lock)
if sg := c.sendq.dequeue(); sg != nil {
// Found a waiting sender. If buffer is size 0, receive value
// directly from sender. Otherwise, receive from head of queue
// and add sender's value to the tail of the queue (both map to
// the same buffer slot because the queue is full).
recv(c, sg, ep, func() { unlock(&c.lock) }, )
return true, true
} if c.qcount > {
// Receive directly from queue
qp := chanbuf(c, c.recvx)
if ep != nil {
typedmemmove(c.elemtype, ep, qp)
}
typedmemclr(c.elemtype, qp)
c.recvx++
if c.recvx == c.dataqsiz {
c.recvx =
}
c.qcount--
unlock(&c.lock)
return true, true
} if !block {
unlock(&c.lock)
return false, false
}
//以上同步非阻塞 //以下同步阻塞
gp := getg()
mysg := acquireSudog()
c.recvq.enqueue(mysg)
//将当前G状态改成等待状态,停止调度
goparkunlock(&c.lock, "chan receive", traceEvGoBlockRecv, ) //当前G被唤醒从这里继续执行
mysg.c = nil
releaseSudog(mysg)
return true, !closed
}
Go channel实现源码分析的更多相关文章
- Netty源码分析第1章(Netty启动流程)---->第3节: 服务端channel初始化
Netty源码分析第一章:Netty启动流程 第三节:服务端channel初始化 回顾上一小节的initAndRegister()方法: final ChannelFuture initAndRe ...
- NIO 源码分析(05) Channel 源码分析
目录 一.Channel 类图 二.begin 和 close 是什么 2.1 AbstractInterruptibleChannel 中的 begin 和 close 2.2 Selector 中 ...
- zookeeper源码分析之三客户端发送请求流程
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...
- MyCat源码分析系列之——前后端验证
更多MyCat源码分析,请戳MyCat源码分析系列 MyCat前端验证 MyCat的前端验证指的是应用连接MyCat时进行的用户验证过程,如使用MySQL客户端时,$ mysql -uroot -pr ...
- gRPC源码分析0-导读
gRPC是Google开源的新一代RPC框架,官网是http://www.grpc.io.正式发布于2016年8月,技术栈非常的新,基于HTTP/2,netty4.1,proto3.虽然目前在工程化方 ...
- dubbo源码分析6-telnet方式的管理实现
dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...
- docker 源码分析 四(基于1.8.2版本),Docker镜像的获取和存储
前段时间一直忙些其他事情,docker源码分析的事情耽搁了,今天接着写,上一章了解了docker client 和 docker daemon(会启动一个http server)是C/S的结构,cli ...
- 最新版ffmpeg源码分析
最新版ffmpeg源码分析一:框架 (ffmpeg v0.9) 框架 最新版的ffmpeg中发现了一个新的东西:avconv,而且ffmpeg.c与avconv.c一个模样,一研究才发现是libav下 ...
- Java IO 之 FileInputStream & FileOutputStream源码分析
Writer :BYSocket(泥沙砖瓦浆木匠) 微 博:BYSocket 豆 瓣:BYSocket FaceBook:BYSocket Twitter ...
随机推荐
- 【毕业】-《伯恩茅斯大学毕业证书》BU一模一样原件
☞伯恩茅斯大学毕业证书[微/Q:2544033233◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归 ...
- 当需要向数据库插入空值时,sql语句的判断
方法如下: 1.int代表整形. 2.string 代表 字符型. 3.datetime ,日期类型判断如下 if(account.date!=Datetime.MinValue) { Str1.Ap ...
- 浅谈surging服务引擎中的rabbitmq组件和容器化部署
1.前言 上个星期完成了surging 的0.9.0.1 更新工作,此版本通过nuget下载引擎组件,下载后,无需通过代码build集成,引擎会通过Sidecar模式自动扫描装配异构组件来构建服务引擎 ...
- python爬虫踩坑教程
我们的目标是爬取下面这个个网址上的2010~2018年的数据 http://stockdata.stock.hexun.com/zrbg/Plate.aspx?date=2015-12-31 获取我们 ...
- 「拥抱开源, 又见 .NET」系列第三次线下活动简报
「拥抱开源, 又见 .NET」 随着 .NET Core的发布和开源,.NET又重新回到人们的视野. 自2016年 .NET Core 1.0 发布以来,其强大的生命力让越来越多技术爱好者对她的未来满 ...
- 学习JVM是如何从入门到放弃的?
前言 只有光头才能变强 JVM在准备面试的时候就有看了,一直没时间写笔记.现在到了一家公司实习,闲的时候就写写,刷刷JVM博客,刷刷电子书. 学习JVM的目的也很简单: 能够知道JVM是什么,为我们干 ...
- SpringIOC原理简述
IOC:控制反转(Inversion of Control,英文缩写为 IOC) 简单来讲就是把代码的控制权从调用方(用户)转变成被调用方(服务端) 以前的代码控制权在调用方,所以要每当程序要更新修改 ...
- arcgis api 4.x for js 结合 react 入门开发系列初探篇(附源码下载)
你还在使用 JQuery 或者 Dojo 框架开发 arcgis api 4.x for js 吗?想试试模块化开发吗?随着前端技术的发展,arcgis api 4.x for js 也有了结合 re ...
- 用samba来创建windows下的文件共享
前言 Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件,而SMB是Server Message Block的缩写,即为服务器消息块 ,SMB主要是作为Microsoft的网络 ...
- [20190402]关于semtimedop函数调用2.txt
[20190402]关于semtimedop函数调用2.txt --//前几天做了sql语句在mutexes上的探究.今天看看_mutex_wait_time设置很大的情况下是否semtimedop会 ...