关于Golang channel的实现
May 06, 2021 am 10:00 AM下面由golang教程栏目给大家介绍关于Golang channel的实现,希望对需要的朋友有所帮助!
一.简介
channel是Go语言在语言级别提供的goroutine间的通信方式,可以使用channel在两个或多个goroutine之间传递消息。channel是进程内通信方式,因此通过channel传递对象的过程和调用函数时的参数传递行为比较一致,比如也可以传递指针。如果需要跨进程通信,建议使用分布式系统来解决,比如使用Socket或者HTTP等通信协议。
channel是类型相关的,也就是说,一个chennel只能传递一种类型的值,这个类型需要在声明channel时指定。注意,在GO语言中channel本身也是一个原生类型,与map之类的类型地位一样,因此channel本身在定义后也可以通过channel传递。
二.底层实现
2.1 hchan结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
- qcount uint // 当前队列中剩余元素个数。
- dataqsiz uint // 环形队列长度,即缓冲区的大小,即make(chan T,N),N。
- buf unsafe.Pointer // 环形队列指针。
- elemsize uint16 // 每个元素的大小。
- closed uint32 // 表示当前通道是否处于关闭状态。创建通道后,该字段设置为0,即通道打开; 通过调用close将其设置为1,通道关闭。
- elemtype *_type // 元素类型,用于数据传递过程中的赋值。
- sendx uint 和 recvx uint是环形缓冲区的状态字段,它指示缓冲区的当前索引 - 支持数组,它可以从中发送数据和接收数据。
- recvq waitq // 等待读消息的goroutine队列。
- sendq waitq // 等待写消息的goroutine队列。
- lock mutex // 互斥锁,为每个读写操作锁定通道,因为发送和接收必须是互斥操作。
2.2 创建过程
2.2.1 写入操作
1.创建带buffer的channel
2.向channel中写入数据
3.3 写入过程如下:
- 锁定整个管道结构。
- 确定写入,尝试从等会带队列等待goroutine,然后将元素直接写入goroutine。
- 如果recvq为空,则确定缓冲区是否可用。如果可用,从当前goroutine复制数据到缓冲区。
- 如果缓冲区已满,则要写入的元素将保存在当前正在执行的goroutine结构中,并且当前goroutine将在sendq中排队并从运行中挂起。
- 写入完成释放锁。
2.2.2 读取过程
- 先读取channel全局锁。
- 尝试sendq从等待队列中获取等待的goroutine。
- 如果有等待的goroutine,且有缓冲区(缓冲区已满),从缓冲区队首取出数据,再从sendq取出一个goroutine。将goroutine中数据存入buf对位,结束读取释放锁。
- 如没有后等待的goroutine,且缓冲区有数据,直接读取缓冲区数据,解释读取释放锁。
- 如果没有等待的goroutine,且没有缓冲或缓冲区域为空,将当前的goroutine加入denq排队,进入睡眠,等待被写goroutine唤醒。结束释放锁。
Atas ialah kandungan terperinci 关于Golang channel的实现. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Artikel Panas

Alat panas Tag

Artikel Panas

Tag artikel panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Bagaimana untuk membaca dan menulis fail dengan selamat menggunakan Golang?

Bagaimana untuk mengkonfigurasi kolam sambungan untuk sambungan pangkalan data Golang?

Persamaan dan Perbezaan antara Golang dan C++

Seberapa curam keluk pembelajaran seni bina rangka kerja golang?

Bagaimana untuk menjana elemen rawak dari senarai di Golang?

Perbandingan kebaikan dan keburukan rangka kerja golang

Apakah amalan terbaik untuk pengendalian ralat dalam rangka kerja Golang?

arahan penggunaan dokumen rangka kerja golang
