当前位置: 首页 > news >正文

阿里云做的网站程序员昆明网站建设公司乐网

阿里云做的网站程序员,昆明网站建设公司乐网,南通做网站的公司有哪些,晋江文学网目录 基本使用 channel 数据结构 阻塞的协程队列 协程节点 构建 channel 写流程 读流程 非阻塞与阻塞 closechan(关闭) 基本使用 创建无缓存 channel c : make(chan int) //创建无缓冲的通道 cc : make(chan int,0) //创建无缓冲的通道 c 创建有缓存 channel c : m…目录 基本使用 channel 数据结构 阻塞的协程队列 协程节点 构建 channel 写流程 读流程 非阻塞与阻塞 closechan(关闭) 基本使用 创建无缓存 channel c : make(chan int) //创建无缓冲的通道 cc : make(chan int,0) //创建无缓冲的通道 c 创建有缓存 channel c : make(chan int, 3) //创建无缓冲的通道 c 例子: package mainimport (fmttime )func main() {c : make(chan int, 3) //创建有缓冲的通道 c//内置函数 len 返回未被读取的缓冲元素数量cap 返回缓冲区大小fmt.Printf(len(c)%d, cap(c)%d\n, len(c), cap(c))go func() {defer fmt.Println(子go程结束)for i : 0; i 3; i {c - ifmt.Printf(子go程正在运行[%d]: len(c)%d, cap(c)%d\n, i, len(c), cap(c))}}()time.Sleep(2 * time.Second) //延时2sfor i : 0; i 3; i {num : -c //从c中接收数据并赋值给numfmt.Println(num , num)}fmt.Println(main进程结束) }channel 数据结构 type hchan struct {qcount uint // total data in the queuedataqsiz uint // size of the circular queuebuf unsafe.Pointer // points to an array of dataqsiz elementselemsize uint16closed uint32elemtype *_type // element typesendx uint // send indexrecvx uint // receive indexrecvq waitq // list of recv waiterssendq waitq // list of send waiterslock mutex } hchanchannel 数据结构 • qcount当前 channel 中存在多少个元素 • dataqsize: 当前 channel 能存放的元素容量 • bufchannel 中用于存放元素的环形缓冲区 • elemsizechannel 元素类型的大小 • closed标识 channel 是否关闭 • elemtypechannel 元素类型 • sendx发送元素进入环形缓冲区的 index • recvx接收元素所处的环形缓冲区的 index • recvq因接收而陷入阻塞的协程队列 • sendq因发送而陷入阻塞的协程队列 lock mutex 锁 阻塞的协程队列 type waitq struct {first *sudoglast  *sudog } waitq阻塞的协程队列 • first队列头部 • last队列尾部 协程节点 sudog用于包装协程的节点 type sudog struct {g *gnext *sudogprev *sudogelem unsafe.Pointer // data element (may point to stack)isSelect boolc *hchan } • ggoroutine协程 • next队列中的下一个节点 • prev队列中的前一个节点 • elem: 读取/写入 channel 的数据的容器; • isSelect标识当前协程是否处在 select 多路复用的流程中 • c标识与当前 sudog 交互的 chan. 构建 channel func makechan(t *chantype, size int) *hchan {elem : t.elem// ...mem, overflow : math.MulUintptr(elem.size, uintptr(size))if overflow || mem maxAlloc-hchanSize || size 0 {panic(plainError(makechan: size out of range))}var c *hchanswitch {case mem 0:// Queue or element size is zero.c (*hchan)(mallocgc(hchanSize, nil, true))// Race detector uses this location for synchronization.c.buf c.raceaddr()case elem.ptrdata 0:// Elements do not contain pointers.// Allocate hchan and buf in one call.c (*hchan)(mallocgc(hchanSizemem, nil, true))c.buf add(unsafe.Pointer(c), hchanSize)default:// Elements contain pointers.c new(hchan)c.buf mallocgc(mem, elem, true)}c.elemsize uint16(elem.size)c.elemtype elemc.dataqsiz uint(size)lockInit(c.lock, lockRankHchan)return } 写流程 func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {// ...//加锁lock(c.lock)// ...//写时存在阻塞读协程if sg : c.recvq.dequeue(); sg ! nil {// Found a waiting receiver. We pass the value we want to send// directly to the receiver, bypassing the channel buffer (if any).send(c, sg, ep, func() { unlock(c.lock) }, 3)return true}//写时不存在阻塞读协程,且缓冲区不满仍有空间if c.qcount c.dataqsiz {// Space is available in the channel buffer. Enqueue the element to send.qp : chanbuf(c, c.sendx)typedmemmove(c.elemtype, qp, ep)c.sendxif c.sendx c.dataqsiz {c.sendx 0}c.qcountunlock(c.lock)return true}//写时不存在阻塞读协程,且缓冲区满了没有空间// ...gp : getg()mysg : acquireSudog()mysg.elem epmysg.g gpmysg.c cgp.waiting mysgc.sendq.enqueue(mysg)atomic.Store8(gp.parkingOnChan, 1)gopark(chanparkcommit, unsafe.Pointer(c.lock), waitReasonChanSend, traceEvGoBlockSend, 2)gp.waiting nilclosed : !mysg.successgp.param nilmysg.c nilreleaseSudog(mysg)return true } 总结:  1.当写时存在阻塞读协程,我们直接用  2.当写时不存在阻塞读协程,且缓冲区不满仍有空间时,我们直接加入环形缓冲区中 3.当写时不存在阻塞读协程,且缓冲区满了没用空间时,加入阻塞写协程队列中 注意: 1.有阻塞读协程和缓冲区满之间只有一个条件符合 2.对于未初始化的 chan写入操作会引发死锁 3.对于已关闭的 chan写入操作会引发 panic. 读流程 读流程与写流程差不多,不同点: 1.加入的是阻塞读队列 2.当环形缓冲区有和无数据时会有不同的操作 注意: 1.读空channel, park挂起,引起死锁 2.channel 已关闭且内部无元素,直接解锁返回 非阻塞与阻塞 区别: 非阻塞模式下读/写 channel 方法通过一个 bool 型的响应参数用以标识是否读取/写入成功. • 所有需要使得当前 goroutine 被挂起的操作在非阻塞模式下都会返回 false • 所有是的当前 goroutine 会进入死锁的操作在非阻塞模式下都会返回 false • 所有能立即完成读取/写入操作的条件下非阻塞模式下会返回 true. 何时进入非阻塞 默认情况下读/写 channel 都是阻塞模式只有在 select 语句组成的多路复用分支中 与 channel 的交互会变成非阻塞模式 在sudog用于包装协程的节点 • isSelect标识当前协程是否处在 select 多路复用的流程中   closechan(关闭) func closechan(c *hchan) {if c nil {panic(plainError(close of nil channel))}lock(c.lock)if c.closed ! 0 {unlock(c.lock)panic(plainError(close of closed channel))}c.closed 1var glist gList// release all readersfor {sg : c.recvq.dequeue()if sg nil {break}if sg.elem ! nil {typedmemclr(c.elemtype, sg.elem)sg.elem nil}gp : sg.ggp.param unsafe.Pointer(sg)sg.success falseglist.push(gp)}// release all writers (they will panic)for {sg : c.sendq.dequeue()if sg nil {break}sg.elem nilgp : sg.ggp.param unsafe.Pointer(sg)sg.success falseglist.push(gp)}unlock(c.lock)// Ready all Gs now that weve dropped the channel lock.for !glist.empty() {gp : glist.pop()gp.schedlink 0goready(gp, 3) 关闭未初始化过的 channel 会 panic • 加锁 • 重复关闭 channel 会 panic • 将阻塞读协程队列中的协程节点统一添加到 glist • 将阻塞写协程队列中的协程节点统一添加到 glist • 唤醒 glist 当中的所有协程. 防止还有协程挂起,没有被唤醒的资源浪费 参考:小徐先生1212 -- Golang Channel实现原理
http://www.hkea.cn/news/14282952/

相关文章:

  • 佛山免费建站平台福州专业网站设计
  • 更换模板对网站seo的影响网站变灰代码 所有浏览器
  • 个人旅游网站建设方案crm管理系统在线使用
  • 好的设计师互动网站seo优化工具哪个好
  • 如何制作wordpress网站地图东莞建设网企业沟通平台
  • 域名怎么和网站绑定软件开发步骤包括哪些
  • 网站添加提醒大学生做网上英语翻译兼职网站
  • 龙岗网站-建设深圳信科桂林网站建设制作
  • 东莞做网站首选杭州百度推广电话
  • 做社交网站的预算网络营销推广方案3000字
  • 地方门户网站赚钱四川seo快速排名
  • 软件网站怎么做的走出趣网站怎么做
  • 哪个网站能在线做司考题目贵州网站建设联系电话
  • 钓鱼链接生成器优化软件排行榜
  • 电子商务网站推广策划方案国外好看的网站设计
  • 制作网站接单怎么做电脑端网站设计稿
  • 网站空间商怎么做房价必涨的十大城市
  • 小公司建网站 优帮云网站做301重定向的作用
  • 取消网站验证码河南最新任免
  • 上海公司查询网站东莞seo建站优化收费
  • 部门做网站优点2023年新闻热点事件摘抄
  • 做风险投资网站做网站需要公司资质吗
  • 网站建设常见问题及解决办法网站内如何做内部链接
  • 廊坊永清网站建设百度搜索风云榜电脑版
  • 汕头网站建设浩森宇特广州市网站建设制作费用
  • 网站建设要注意哪些事情芜湖北京网站建设
  • 做最最优秀的视频网站泉州公司网站建设
  • 签名能留链接的网站网站建设价格差别
  • 如何利用模板建站网站底部版权信息代码
  • 高端的平面设计网站ios7风格网站