一文读懂Channel设计.docxVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
? ? 一文读懂Channel设计 ? ? 在Go中,要理解channel,首先需要认识goroutine。 一、为什么会有goroutine 现代操作系统中为我们提供了三种基本的构造并发程序的方法:多进程、I/O多路复用和多线程。其中最简单的构造方式当属多进程,但是多进程的并发程序,由于对进程控制和进程间通信开销巨大,这样的并发方式往往会很慢。 因此,操作系统提供了更小粒度的运行单元:线程(确切叫法是内核线程)。它是一种运行在进程上下文中的逻辑流,线程之间通过操作系统来调度,其调度模型如下图所示。 多线程的并发方式,相较于多进程而言要快得多。但是由于线程上下文切换总是不可避免的陷入内核态,它的开销依然较大。那么有没有不必陷入内核态的运行载体呢?有,用户级线程。 用户级线程的切换由用户程序自己控制,不需要内核干涉,因此少了进出内核态的消耗。 这里的用户级线程就是协程(coroutine),它们的切换由运行时系统来统一调度管理,内核并不知道它的存在。协程是抽象于内核线程之上的对象,一个内核线程可以对应多个协程。但最终的系统调用仍然需要内核线程来完成。注意,线程的调度是操作系统来管理,是一种抢占式调度。而协程不同,协程之间需要合作,会主动交出执行权,是一种协作式调度,这也是为何被称为协程的原因。 Go天生在语言层面支持了协程,即我们常说的goroutine。Go的runtime系统实现的是一种M:N调度模型,通过GMP对象来描述,其中G代表的就是协程,M是线程,P是调度上下文。在Go程序中,一个goroutine就代表着一个最小用户代码执行流,它们也是并发流的最小单元。 二、channel的存在定位 从内存的角度而言,并发模型只分两种:基于共享内存和基于消息通信(内存拷贝)。在Go中,两种并发模型的同步原语均有提供:sync.*和atomic.*代表的就是基于共享内存;channel代表的就是基于消息通信。而Go提倡后者,它包括三大元素:goroutine(执行体),channel(通信),select(协调)。 Do not communicate by sharing memory; instead, share memory by communicating. 在Go中通过goroutine+channel的方式,可以简单、高效地解决并发问题,channel就是goroutine之间的数据桥梁。 Concurrency is the key to designing high performance network services. Go’s concurrency primitives (goroutines and channels) provide a simple and efficient means of expressing concurrent execution. 以下是一个简单的channel使用示例代码。 func goroutineA(ch -chan int) { fmt.Println([goroutineA] want a data) val := - ch fmt.Println([goroutineA] received the data, val) } func goroutineB(ch chan- int) { time.Sleep(time.Second*1) ch - 1 fmt.Println([goroutineB] send the data 1) } func main() { ch := make(chan int, 1) go goroutineA(ch) go goroutineB(ch) time.Sleep(2*time.Second) } 上述过程趣解图如下 三、channel源码解析 channel源码位于src/go/runtime/chan.go。本章内容分为两部分:channel内部结构和channel操作。 3.1 channel内部结构 ch := make(chan int,2) 对于以上channel的申明语句,我们可以在程序中加入断点,得到ch的信息如下。 很好,看起来非常的清晰。但是,这些信息代表的是什么含义呢?接下来,我们先看几个重要的结构体。 hchan 当我们通过make(chan Type, size)生成channel时,在runtime系统中,生成的是一个hchan结构体对象。源码位于src/runtime/chan.go type hchan struct { qcount uint // 循环队列中数据数 dataqsiz uint // 循环队

文档评论(0)

科技之佳文库 + 关注
官方认证
文档贡献者

科技赋能未来,创新改变生活!

版权声明书
用户编号:8131073104000017
认证主体重庆有云时代科技有限公司
IP属地浙江
统一社会信用代码/组织机构代码
9150010832176858X3

1亿VIP精品文档

相关文档