Yra's blog Yra's blog
Homepage
  • LeetCode周赛
  • Acwing周赛
  • 刷题整理
  • 题解
  • CPP
  • Golang
  • System

    • MIT6.S081 Labs
  • Computer Networking

    • CS144: Computer Networking
  • DataBase

    • MySQL
    • Redis
  • Others

    • ......
  • Paper Reading

    • Petri Net
  • Static Analysis

    • NJU Course Notes
  • Deep Learning

    • Dive into Deep Learning
Casual Records
Archives

Yra

Only a vegetable dog.
Homepage
  • LeetCode周赛
  • Acwing周赛
  • 刷题整理
  • 题解
  • CPP
  • Golang
  • System

    • MIT6.S081 Labs
  • Computer Networking

    • CS144: Computer Networking
  • DataBase

    • MySQL
    • Redis
  • Others

    • ......
  • Paper Reading

    • Petri Net
  • Static Analysis

    • NJU Course Notes
  • Deep Learning

    • Dive into Deep Learning
Casual Records
Archives
  • CPP

  • Golang

    • Go 语言中的 GC 问题整理
    • Go 语言中的 Channel 相关问题整理
    • Programming Languages
    • Golang
    Yra
    2023-09-06
    目录

    Go 语言中的 Channel 相关问题整理

    # Channel

    • Go 语言中,不通过共享内存实现通信,而通过通信来实现共享内存

    • Go 语言的 CSP(通信顺序进程)并发模型,是通过 goroutine 和 channel 实现的

    • channel 遵守 FIFO 原则,分为有缓冲区和无缓冲区

    • 假设 ch 是函数栈上的一个指针,其指向堆中的 hchan 数据结构

      • hchan 支持多个协程的并发访问,所以包含一把互斥锁
      • 包含缓冲区指针(缓冲区是一个数组)
      • 包含已经存储了多少数据
      • 包含最多能存储多少数据
      • 包含每个元素占多大空间
      • 因为内存复制、gc 等机制依赖于数据类型,所以包含一个指针指向元素类型的类型元数据
      • 包含发送、接受队列和发送、接收下标
      • 包含关闭状态
      type hchan struct {
          qcount   uint           // 已经存储的元素数量
          dataqsiz uint           // 最多存储的元素数量
          buf      unsafe.Pointer // 缓冲区(循环数组)指针
          elemsize uint16         // 每个元素的大小
      
          closed   uint32  	    // 关闭标志
          elemtype *_type         // 元素类型的类型元数据指针
      
          sendx    uint           // 下一次发送数据的下标
          recvx    uint           // 下一次读取数据的下标
      
          recvq    waitq  		// 接受队列
          sendq    waitq  		// 发送队列
      
          lock mutex 				// 互斥锁,支持多协程访问
      }
      
    • 缓冲区是一个环形缓冲区 Ring Buffer

    • 发送数据时,

      • 不发生阻塞的情况:缓冲区非空且有空闲区域、缓冲区为空且有协程等待接收数据
      • 会发生阻塞的情况:channel 为 nil、缓冲区为空且没有协程等待接收数据、缓冲区满了且没有协程等待接收数据
      • 可以使用 select + default 的非阻塞式写法
      select {
      case ch<- 10:
      // ...
      default:
      // ...
      }
      
    • 接收数据时,

      • 不发生阻塞的情况:缓冲区非空有数据、缓冲区为空且有协程等待发送数据
      • 会发生阻塞的情况:channel 为 nil、缓冲区为空且没有协程等待发送数据、有缓冲区但没有数据且没有协程等待发送数据
      • 也可以使用 select + default 的非阻塞写法
    • 多路 select 中,每个 case 可以是一个 channel 的发送 或 接受操作,其中 default 可选

    select {
    case a = <-ch1:
    // ...
    case ch2 <- b
    }
    
    • 用 channel 共享内存可以解耦生产者和消费者,但容易引发阻塞甚至死锁
    #Programming Languages#Golang
    Last Updated: 9/6/2023, 4:49:24 PM
    Go 语言中的 GC 问题整理

    ← Go 语言中的 GC 问题整理

    最近更新
    01
    408 计组笔记
    07-19
    02
    Dive into Deep Learning
    01-27
    03
    25 考研随记
    11-27
    更多文章>
    Theme by Vdoing | Copyright © 2022-2025
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式