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

凡客做网站怎么样浅谈网站页面框架设计

凡客做网站怎么样,浅谈网站页面框架设计,做食品怎样选网站,机械配件采购平台go chan底层分析 底层源码hchanmakechan 方法 环形队列阻塞机制向管道写数据流程图源码 从管道读数据流程图源码 关闭通道 底层源码 hchan type hchan struct {qcount uint // 当前队列中剩余元素个数dataqsiz uint // 环形队列长度#xff0c;即可以… go chan底层分析 底层源码hchanmakechan 方法 环形队列阻塞机制向管道写数据流程图源码 从管道读数据流程图源码 关闭通道 底层源码 hchan type hchan struct {qcount uint // 当前队列中剩余元素个数dataqsiz uint // 环形队列长度即可以存放的元素个数也就是通道的缓冲区大小buf unsafe.Pointer // 是一个指向环形队列的指针elemsize uint16 // 存储通道中每个元素的大小单位是字节。closed uint32 // 标识关闭状态elemtype *_type // 元素类型sendx uint // 队列下标指示元素写入时存放到队列中的位置recvx uint // 队列下标指示元素从队列的该位置读出recvq waitq // 等待读消息的goroutine队列sendq waitq // 等待写消息的goroutine队列lock mutex // 互斥锁chan不允许并发读写 }读消息协程队列recvq 和 写消息协程队列sendq 分别是接收- channel)和 发送channel - xxx的 协程 抽象出来的结构体sudog的队列是个双向链表。 type waitq struct {first *sudoglast *sudog }makechan 方法 makechan 是一个内部方法用于创建通道。它位于 src/runtime 目录下负责通道内存的分配、初始化通道结构体等操作。makechan 方法是由 Go 运行时调用的它不会直接出现在普通用户代码中而是与 Go 的低级运行时管理密切相关。 创建一个管道会在 heap 中实例化一个 hchan 对象并返回这个对象的指针。 func makechan(t *chantype, size int) *hchan {// t 是由 Go 编译器在编译时生成的。// elem 是通道元素的类型描述符*chantype它包含了关于通道元素类型的各种信息。// elem.Size_ 是 elem 结构体中的字段表示通道元素类型的大小以字节为单位。// 例如如果通道的元素类型是 int那么 elem.Size_ 就是 int 类型的大小通常是 4 字节或 8 字节具体取决于平台。大小是编译时确定的并通过 elem.Size_ 字段存储在 chantype 中。elem : t.Elem// 1.元素大小检查查通道中元素的大小是否超过了 64KB1 16。通道中每个元素的大小不能超过 64KB超出此限制会导致不合法的元素类型。if elem.Size_ 116 {throw(makechan: invalid channel element type)}// 2.对齐条件检查检查 hchan 结构体的大小和元素的对齐要求是否符合系统的对齐规则。如果不符合将抛出异常。if hchanSize%maxAlign ! 0 || elem.Align_ maxAlign {throw(makechan: bad alignment)}// 3.计算所需内存计算通道缓冲区所需的内存大小。elem.Size_ 是单个元素的大小size 是通道的大小即缓冲区中的元素个数。如果计算结果溢出或者超出了最大分配内存限制代码会抛出异常。mem, overflow : math.MulUintptr(elem.Size_, uintptr(size))if overflow || mem maxAlloc-hchanSize || size 0 {panic(plainError(makechan: size out of range))}// 4.内存分配mallocgc 函数它会在 Go 的垃圾回收器中分配内存。mallocgc 会根据需要将内存注册到垃圾回收系统并处理内存的初始化var c *hchanswitch {// mem 0如果元素大小为 0即元素为零字节则只分配 hchan 结构体所需的内存。case mem 0:c (*hchan)(mallocgc(hchanSize, nil, true))c.buf c.raceaddr()// elem.PtrBytes 0如果元素类型不包含指针即元素是简单数据类型则通道和缓冲区内存会一次性分配。case elem.PtrBytes 0:c (*hchan)(mallocgc(hchanSizemem, nil, true))c.buf add(unsafe.Pointer(c), hchanSize)// 其他情况如果元素类型包含指针则首先为 hchan 分配内存然后单独为元素数据缓冲区分配内存。default:c new(hchan)c.buf mallocgc(mem, elem, true)}// 5.初始化通道信息c.elemsize uint16(elem.Size_) // 存储单个元素的大小c.elemtype elem // 存储元素类型的描述信息c.dataqsiz uint(size) // 存储缓冲区的大小即通道中可以存储的元素数量lockInit(c.lock, lockRankHchan) // 初始化 hchan 结构体中的锁用于保证并发操作时的同步// 6.调试输出如果启用了调试模式Go 运行时会打印通道创建的信息用于调试。if debugChan {print(makechan: chan, c, ; elemsize, elem.Size_, ; dataqsiz, size, \n)}return c }环形队列 chan内部实现了一个环形队列作为其缓冲区队列的长度是创建chan时指定的。 下图展示了一个可缓存6个元素的channel示意图 dataqsiz 表示了队列长度为6即可缓存6个元素buf 指向队列的内存qcount 表示队列中还有两个元素sendx 表示后续写入的数据存储的位置取值[0, 6)recvx 表示从该位置读取数据, 取值[0, 6) 阻塞机制 一个协程向一个 管道读数据如果管道缓冲区为空或者没有缓冲区当前的协程会被加入到 读消息协程队列recvq中并且被挂起来直到对应的条件满足时例如缓冲区有数据它会被唤醒并继续执行 一个协程向一个管道写数据如果管道缓冲区已经满了或者没有缓冲区当前的协程会被加入到 写消息协程队列sendq 中并且被挂起来直到对应的条件满足时例如缓冲区有空间它会被唤醒并继续执行。 注意处于等待队列中的协程会在其他协程操作管道时被唤醒具体如下 因读阻塞的协程会被向管道写人数据的协程唤醒。因写阻塞的协程会被从管道读数据的协程唤醒。 注意一般不会出现 读消息协程队列recvq 和 写消息协程队列sendq 中同时有协程排队的情况只有一个例外那就是同一个协程使用 select 语句向管道一边写数据、一边读数据此时协程会分别位于两个等待队列中。 向管道写数据 向一个管道中写数据的过程如下 如果缓冲区中有空余位置则将数据写人缓冲区结束写消息过程。如果缓冲区中没有空余位置则将 写消息协程 加人 写消息协程队列sendq进入睡眠并等待被 读协程 唤醒。特殊情况直接将准备写的数据传递给 读消息协程队列recvq 。具体如下当 读消息协程队列recvq 中有协程等待时会将准备写的数据直接传递给 读消息协程队列recvq 中的第一个 读消息协程而不需要通过缓冲区。这是一个优化手段避免了无谓的缓冲区操作。 流程图 注意写消息的时候如果是无缓冲管道直接写消息而且 读消息协程队列 中没有协程这个时候就会直接阻塞报错要确保在写消息前 读消息协程队列 不为空。 源码 特殊情况 直接将数据传递给 读消息协程队列recvq 。如果 读消息协程队列recvq 中有 读消息协程 等待接收数据那么直接将发送的数据传递给 读消息协程 跳过缓冲区。 阻塞操作 如果管道缓冲区已满并且没有 读消息协程队列recvq 中的 读消息协程 在等待则发送操作会被阻塞直到有空间可以写入数据或者接收协程完成了数据接收。 协程阻塞和唤醒机制 在 写消息协程 被阻塞时即没有缓冲区了而且 读消息协程队列recvq 中为空程序会将其添加到 写消息协程队列sendq 中并通过 gopark 将其置于等待状态。 从管道读数据 从一个管道读数据的简单过程如下 如果缓冲区中有数据则从缓冲区取出数据结束读消息过程。如果缓冲区中没有数据则将 读消息协程 加入 读消息协程队列recvq进入睡眠并等待被 写消息协程 唤醒。 同样在实现时有个小技巧如果 写消息协程队列sendq 不为空且没有缓冲区那么此时将直接从 写消息协程队列sendq 的第一个写消息协程 中获取数据。 流程图 源码 通道已关闭且没有数据如果通道已关闭且缓冲区没有数据qcount 0接收者会清理数据如果存在的话释放锁然后返回。 通道已关闭但缓冲区有数据如果通道已关闭但缓冲区中有数据接收者可以正常接收数据。 通道未关闭且有等待发送的数据如果通道未关闭并且 写消息协程队列sendq 中有等待写的消息接收者将直接从 写消息协程队列sendq 中获取数据。 略… 关闭通道 关闭管道时会把 读消息协程队列recvq 中的 读消息协程 全部唤醒这些协程获取的数据都为对应类型的零值。同时还会把 写消息协程队列sendq 中的 写消息协程 全部唤醒但这些协程会触发 panic。 除此之外其他会触发 panic 的操作还有 关闭值为nil 的管道。关闭已经被关闭的管道。向已经关闭的管道写入数据。 参考 go专家编程 图解Go的channel底层实现 【幼麟实验室】Golang合辑
http://www.hkea.cn/news/14385930/

相关文章:

  • 旅游网站开发的背景为什么要创建网站子目录
  • 有了网站 域名然后么做公司简介模板英文版
  • 合肥培训网站推广个人做网站接装修活哪个网站好
  • 正邦做网站吗wordpress连载小说插件
  • 网站之家查询域名软文营销
  • ui设计师mike个人网站舟山集团网站建设
  • 做50个网站做标签的网站
  • 美食网站html静态给wordpress加相册
  • 小说网站开发项目简介wordpress 漂浮插件
  • 网站设计作品网站做多个镜像
  • 没有网站怎么做百度竞价公司起名打分最准的免费网站
  • asp做静态网站农业信息中心网站建设
  • 凡客优品家居官方网站全国最大工地招工网
  • 小马厂网站建设开平建设局网站
  • 网站被百度惩罚放弃东莞网站建设怎么收费
  • 西安网站制作的公司网上购物网站建设论文
  • 长沙专业做网站公司哪家好设计师网站有哪些销售定制家具
  • 手表网站建设短视频推广员干嘛的
  • 泉州网站建设轩奇网讯.net 网站开发
  • 做网站郴州字体在线设计网站
  • 深圳建站模板建站陕西建设信息网
  • 怎样制作html个人网站九龙坡网站建设
  • 网站实名认证怎么做第一个做电子商务的网站
  • 下沙网站建设企业官网 开源
  • 在中国怎么做国外网站陕西省建设厅网站官网企业月报
  • 网络网站维护费怎么做会计分录电商设计的前景
  • 自己做网站做什么内容广告推广广告
  • 罗湖商城网站建设哪家技术好微信小程序功能介绍
  • 网站服务器在哪里梁山做网站
  • 外贸网站模板建设wordpress 唯艾迪