go channel底层实现

本文阅读 3 分钟
首页 golang 正文
题目来源:拼多多

答案:ORVR

在了解channel底层实现前,先得明白go的并发模型,在其他的语言中java、Python中的并发模型基本都是基于操作系统的线程,并发执行单元(线程)之间的通信一般就是用操作系统提供的线程或进程间的通信原语,如共享内存、信号、管道、消息队列、套接字等,最广泛的则是共享内存的并发模型

go语言从程序设计当初,就是解决上面传统并发模型作为模型,引入 CSP(Communicationing Sequential Processes-通信顺序进程)并发模型。

而在其中实现通信的就是channel

//下面就是channel的源码,由一个hchan实现类

type hchan struct {

    // chan 里元素数量

    qcount uint

    // chan 底层循环数组的长度

    dataqsiz uint

    // 指向底层循环数组的指针

    // 只针对有缓冲的 channel

    buf unsafe.Pointer

    // chan 中元素大小

    elemsize uint16

    // chan 是否被关闭的标志

    closed uint32

    // chan 中元素类型

    elemtype *_type // element type

    // 已发送元素在循环数组中的索引

    sendx uint // send index

    // 已接收元素在循环数组中的索引

    recvx uint // receive index

    // 等待接收的 goroutine 队列

    recvq waitq // list of recv waiters

    // 等待发送的 goroutine 队列

    sendq waitq // list of send waiters

    // 保护 hchan 中所有字段

    lock mutex

}

channel底层结构图

buf指向一个底层的循环数组,只有设置为有缓存的channel才会有buf

sendx和recvx分别指向底层循环数组的发送和接收元素位置的索引

sendq和recvq分别表示发送数据的被阻塞的goroutine和读取数据的goroutine,这两个都是一个双向链表结构

sendq和recvq 的结构为 waitq 类型,sudog是对goroutine的一种封装

type waitq struct {

    first *sudog

    last *sudog

}

channel 的发送和接收操作本质上都是 “值的拷贝”,无论是从 sender goroutine 的栈到 chan buf,还是从 chan buf 到 receiver goroutine,或者是直接从 sender goroutine 到 receiver goroutine。

channel读取写入流程

操作nil channelclosed channelnot nil,not channel
closepanicpanic正常关闭
读<-ch阻塞读到对应类型的零值阻塞或正常读取数据,缓冲型channel为空或非缓冲型channel等待发送者时会阻塞
写ch<-阻塞panic阻塞或正常写入数据,非缓冲型channel没有等待接收者或缓冲型channel buf满时会被阻塞
本文来自投稿,不代表本站立场,如若转载,请注明出处:
了解中间件吗?有什么好处?
« 上一篇 09-17
Go 高并发的特点
下一篇 » 09-17

发表评论

发表评论