自学内容网 自学内容网

Golang——channel

channel是Go在语言层面提供的协程间的通信方式。通过channel我们可以实现多个协程之间的通信,并对协程进行并发控制。

使用注意:

  1. 管道没有缓冲区时,从管道中读取数据会阻塞,直到有协程向管道中写入数据。类似地,向管道中写入数据会阻塞,直到有协程从管道读取数据。

  2. 管道有缓冲区时,从管道中读取数据,如果缓冲区没有数据也会进行阻塞,直到有协程向管道中写入数据。向管道写入数据,如果缓冲区已满也会进行阻塞,直到有协程从管道中读取数据。

  3. 对于一个值为nil的管道,无论读写数据都会阻塞,而且是永久阻塞。

  4. 读取已经关闭的管道,如果管道有缓冲区的话,会获取缓冲区中的数据,如果缓冲区中没有数据会返回零值

  5. 向已经关闭的管道中写入数据会触发panic【panic:send on closed channel】

  6. 读取管道的时候会返回两个值,第一个是从管道中取出元素的值,第二个是检测管道的缓冲区中是否还有元素,如果有返回true,没有返回false。

    1. 我们从一个已经关闭的管道中读取元素,如果这一个管道有缓冲区并且缓冲区中有元素,那么会获取缓冲区中的元素并true。如果这一个缓冲区没有元素,那么就会返回该管道类型的零值和false。

底层实现:

channel的底层数据结构实现源码位置:src/runtime/chan.go:hchan

type hchan struct {
    qcount   uint           // 当前队列中的元素个数
    dataqsiz uint           // 队列的长度
    buf      unsafe.Pointer // 指向一个数组空间,channel中的队列是通过数组实现的
    elemsize uint16         // 类型的大小
    closed   uint32         // 是否已经关闭
    elemtype *_type         // 管道的类型
    sendx    uint           // 元素写入队列中的下标位置
    recvx    uint           // 从环形队列中读取元素的位置
    recvq    waitq          // 待读取队列,阻塞中
    sendq    waitq          // 待写入队列,阻塞中
    lock     mutex          //锁,防止多个协程同时操作一个管
}

channel的底层实现由环形队列、类型信息、等待队列三部分组成。

  1. 创建管道的过程实际就是初始化hchan结构体的过程

  2. 向管道中写入数据时

    1. 如果缓冲区有空余位置,则将数据写入缓冲区,结束发送过程

    2. 如果缓冲区中没有位置,则将当前协程加入sendq队列,进入睡眠并等待被取协程唤醒。如果读取队列不为空,则会直接将数据写入到等待读取的协程中,并等待唤醒读取的协程。【先检查recvq是否为空,再检查buf是否有空位置】

  3. 从管道中读取数据

    1. 如果缓冲区有数据,则直接读取缓冲区中数据,结束读取过程

    2. 如果缓冲区中没有数据,则将当前协程加入recvq队列,进入睡眠并等待被写入协程唤醒。如果写入队列不为空,并且没有缓冲区,那么此时将直接从sendq中的第一个协程获取数据。【先检查sendq是否为空,之后根据判断,如果为空,检查环形队列中是否有数据;如果不为空,检查是否有缓冲区,如果有缓冲区将取出缓冲区中的第一个数据,并将sendq队列中的第一个协程中的数据写入到buf中,如果没有缓冲区,则直接读取sendq队列中的第一个协程】

  4. 关闭管道

      关闭管道的时候会把recvq中的协程全部唤醒,这些协程获取到的数据都为对应类型的零值。同时也会把sendq队列中的协程全部唤醒,但是这些协程会触发panic。

常见用法:

  • switch-case 随机选择一个可执行的case进行执行,如果所有的case都不能执行,则执行default,如果没有default的话,则进行阻塞等待,直到有一个可执行的case。
  • for-range 可以作用于管道,如果遍历的管道没有关闭,则会将管道中的所有的元素遍历并取出,并阻塞读取管道中的元素;如果遍历的是一个已经关闭的管道,则会取出管道中的所有的元素,并正常关闭。

原文地址:https://blog.csdn.net/wangye135/article/details/139778534

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!