go channel 通道
一、底层实现
1、数据结构
type hchan struct {qcount uint // total data in the queuedataqsiz uint // size of the circular queuebuf unsafe.Pointer // points to an array of dataqsiz elementselemsize uint16closed uint32timer *timer // timer feeding this chanelemtype *_type // element typesendx uint // send indexrecvx uint // receive indexrecvq waitq // list of recv waiterssendq waitq // list of send waiters// lock protects all fields in hchan, as well as several// fields in sudogs blocked on this channel.//// Do not change another G's status while holding this lock// (in particular, do not ready a G), as this can deadlock// with stack shrinking.lock mutex
}type waitq struct {first *sudoglast *sudog
}
channel 用于 goroutine 之间通信和同步。主要由一个环形缓冲区(对于带缓冲的 channel)和两个指针(读指针和写指针)组成。每个 channel 还有一个锁(通常是自旋锁)来保证并发安全。
主要结构:环形缓冲区+读写指针+读写等待队列+锁
2、发送与接收
发送与接收是相对于协程而言的。
- 发送操作(
chan <- value)会检查channel是否已满:- 如果是无缓冲的
channel,发送会阻塞直到有接收操作。 - 如果是有缓冲的
channel,发送会阻塞直到有空间可用。
- 如果是无缓冲的
- 接收操作(
value := <-chan)会检查channel是否为空:- 如果是无缓冲的
channel,接收会阻塞直到有发送操作。 - 如果是有缓冲的
channel,接收会阻塞直到有数据可读
- 如果是无缓冲的
3、发送队列(sendq)和接收队列(recvq)
-
recvq 队列:当一个 goroutine 执行接收操作时,Go 调度器会检查 channel 的状态,接收的 goroutine 会被挂起,并加入到
recvq队列。 -
sendq 队列:当一个 goroutine 执行发送被阻塞时,发送的 goroutine 会被挂起,并加入到
sendq队列。
发送和接收队列是FIFO队列,阻塞线程按先进先出顺序被调度,活跃线程优先于阻塞队列中的线程被调度。
4、调度
调度器会负责管理协程的状态,协程被channel阻塞时进入等待队列,此时调度器可以将其他可运行的 goroutine 调度到 CPU 上。
二、内存管理:
1、内存分配
创建channel时分配内存,channel 内存的分配是通过内存分配器来完成的,它会根据需要为 channel 结构体和缓冲区(如果有)分配内存。
channel的结构:channel是一个指向chan类型的结构体,这个结构体包含了channel的基本信息(例如缓冲区大小、读写指针等)。- 缓冲区(如果是缓冲
channel):如果channel是缓冲的(即使用make(chan Type, size)创建的channel),Go 还需要为channel分配一个固定大小的缓冲区,以便存储数据。缓冲区的大小是channel类型的元素大小乘以缓冲区的长度。
2、内存回收
当一个 channel 被销毁或不再有任何引用时,它占用的内存会被垃圾回收器回收。
channel是引用类型,它本身是一个指针,指向一个底层的数据结构。这个底层结构体包含了与channel操作相关的数据,如缓冲区、队列、读写指针等- 由于
channel的底层数据结构需要在堆上进行管理,因此即使它在栈上有一个指针,实际的数据存储通常是在堆上,特别是当它的生命周期超过函数作用域时。 - 通过 逃逸分析,Go 运行时决定是否将
channel分配到栈上或堆上。如果channel在函数外部被使用(例如通过返回值或传递给其他协程),它会被分配到堆上。 - 如果
channel仅在一个函数内部,并且没有被返回或传递出去(即它的生命周期完全在栈帧内),Go 运行时可能会将它分配到栈上。这个优化是由 Go 运行时的逃逸分析(escape analysis)决定的。如果channel的引用没有逃逸出函数,它可能会分配在栈上;否则,它将分配在堆上。
3、回收时机
- 当
channel不再被引用时:如果channel变量超出了作用域,或者所有引用该channel的变量都被置为nil或销毁,垃圾回收器会将该channel标记为可回收对象。下一次 GC 执行时,它会回收这个channel占用的内存。 channel的缓冲区:如果channel是一个带缓冲的channel(make(chan T, N)),那么在回收channel结构本身时,缓冲区也会被回收。
4、内存分配和垃圾回收的优化
Go 的垃圾回收器会尽可能地减少对内存的管理开销,但当涉及到大量的 channel 操作时,频繁的内存分配和垃圾回收可能会对性能造成影响。为了减少这种影响,可以考虑以下优化:
- 复用
channel:如果可能的话,复用已经创建的channel,而不是每次都重新创建。 - 避免大缓冲区的
channel:如果channel的缓冲区过大,可能会占用大量内存,造成内存压力。使用适当大小的缓冲区可以减少内存消耗。 - 及时关闭
channel:在不再需要channel时,应该尽早关闭它,或者确保channel变量没有持续的引用。
channel 的关闭并不会直接触发垃圾回收,关闭 channel 只是告诉协程可以停止从该 channel 接收数据。在使用带缓冲区的 channel 时,关闭 channel 还意味着缓冲区中未处理的数据将无法再被写入。虽然关闭 channel 本身不影响垃圾回收的触发,但是关闭 channel 可以帮助协程更快地退出,从而可能减少内存泄漏的风险。如果一个 channel 被关闭且没有任何活跃的协程在使用它,那么这个 channel 很可能会更快地被垃圾回收器回收。
相关文章:
go channel 通道
一、底层实现 1、数据结构 type hchan struct {qcount uint // total data in the queuedataqsiz uint // size of the circular queuebuf unsafe.Pointer // points to an array of dataqsiz elementselemsize uint16closed uint32timer *t…...
论文阅读:Computational Long Exposure Mobile Photography (二)
这篇文章是谷歌发表在 2023 ACM transaction on Graphic 上的一篇文章,介绍如何在手机摄影中实现长曝光的一些拍摄效果。 Abstract 长曝光摄影能拍出令人惊叹的影像,用运动模糊来呈现场景中的移动元素。它通常有两种模式,分别产生前景模糊或…...
基于SSM+小程序的高校寻物平台管理系统(失物1)
👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 本基于微信小程序的高校寻物平台有管理员,用户以及失主三个角色。 1、管理员功能有个人中心,用户管理,失主管理,寻物启示管理,拾…...
gerrit 搭建遇到的问题
1、启动Apache,端口被占用 : AH00072: make sock: could not bind to address (0S 10048)通常每个套接字地址(协议/网络地址/端口)只允许使用一次。: AH00072: make sock: could not bind to address 0.0.0.:443 a AH00451: no listening sockets available, shutti…...
UBUNTU查看CPU核心数
UBUNTU查看CPU核心数 前言一、使用lscpu命令1. 执行命令2. 查看输出 二、使用/proc/cpuinfo文件1. 查看文件2. 解释输出 三、使用nproc命令1. 执行命令2. 查看输出 四、使用htop或top工具1. 使用htop2. 使用top 五、使用inxi命令1. 执行命令2. 查看输出 六、使用图形界面工具1.…...
【JS】声明提升与块级作用域
我是目录 引言声明提升声明提升的理解函数表达式声明提升总结代码生成与查找变量的过程代码生成词法分析( Tokenizing/Lexing)语法分析( Parsing)代码生成生成代码总结查找变量不同版本中的执行上下文不同版本对执行上下文的定义let/constlet特点const特点let/const声明的变…...
Flink的流、批处理
Flink的数据流处理,是持续流模型,数据不会落地,上游和下游的Task同时启动,等待数据的到达,Flink的批处理还是用的MapReduce计算模型,先处理map端,再执行reduce端。 flink的流处理(STREAMING)&a…...
学习方法该升级了,AI时代的弯道超车:【心流学习法】行动与意识合一的巅峰进化
你是否曾感到内心如荒漠般干涸,面对浩瀚的知识海洋,热情逐渐消磨殆尽? 你是否渴望忘却时间的流逝,心无旁骛,与知识展开一场纯粹而深邃的对话? 在AI时代,智能体处理数据、知识迭代的速率让人…...
【大模型LLM面试合集】大语言模型架构_chatglm系列模型
chatglm系列模型 1.ChatGLM 1.1 背景 主流的预训练框架主要有三种: autoregressive自回归模型(AR模型):代表作GPT。本质上是一个left-to-right的语言模型。通常用于生成式任务,在长文本生成方面取得了巨大的成功&a…...
深入理解 Kafka:分布式消息队列的强大力量
一、引言 在现代分布式系统中,消息队列扮演着至关重要的角色,而 Kafka 作为其中的佼佼者,以其高吞吐量、可扩展性和持久性等特点被广泛应用。无论是处理海量的日志数据、实时的用户交互信息,还是复杂的微服务间通信,Ka…...
LabVIEW 离心泵机组故障诊断系统
开发了一套基于LabVIEW图形化编程语言设计的离心泵机组故障诊断系统。系统利用先进的数据采集技术和故障诊断方法,通过远程在线监测与分析,有效提升了离心泵的预测性维护能力,保证了石油化工生产的连续性和安全性。 项目背景及意义 离心泵作…...
GEE土地分类——土地分类的原始remap转化原始的土地分类名称
简介 GEE土地分类——土地分类的原始remap转化原始的土地分类名称 函数 first(image2) Selects the value of the first value for each matched pair of bands in image1 and image2. If either image1 or image2 has only 1 band, then it is used against all the bands…...
一些关于云电脑与虚拟化东西
前言 好久没有更新了,在进行自我校准。 云计算是什么? 云计算是一种模型,它使得用户能够随时随地、方便地、按需访问共享的可配置计算资源池(例如,网络、服务器、存储、应用程序和服务),这些资…...
Java实现图片转pdf
该方法可以选择多个图片是否合并为一个pdf输出,也可以选择图片为横向或者纵向输出,也可以选择pdf页面为A3或者A4 第一步 <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version…...
【iOS】使用AFNetworking进行网络请求
文章目录 前言AFNetworkingAFNetworking 的核心组件AKNetworking库的常用方法使用AKNetworking进行网络请求的步骤和代码示例 总结 前言 在暑假写天气预报项目时,我们已经接触到网络请求,当时我们是使用URLSession类,即Foundation框架中用于管…...
ThingsBoard规则链节点:RPC Call Reply节点详解
引言 1. RPC Call Reply 节点简介 2. 节点配置 2.1 基本配置示例 3. 使用场景 3.1 设备控制 3.2 状态查询 3.3 命令执行 4. 实际项目中的应用 4.1 项目背景 4.2 项目需求 4.3 实现步骤 5. 总结 引言 ThingsBoard 是一个开源的物联网平台,提供了设备管理…...
【AI换装整合包及教程】OOTDiffusion:以AI技术引领的时尚换装革命
在当今数字化快速发展的时代,人工智能(AI)技术正以前所未有的速度改变着我们的生活。从智能家居到自动驾驶,从在线教育到虚拟现实,AI的应用范围正在不断扩展。而在时尚领域,一款名为OOTDiffusion࿰…...
排序算法详细总结
算法 定义:算法是解决特定问题的明确步骤集合。算法的效率通常用时间复杂度和空间复杂度来衡量。 排序算法 定义:排序算法是计算机科学中用于对元素序列进行排序的一系列算法。排序算法在各种应用中都非常常见,从简单的数据处理到复杂的数…...
uniapp MD5加密
安装: npm install js-md5 -D 引入: import Md5 from js-md5 需求加密一个对象, login_form: {openId: 123456789,phone: ,scenario: 656677,phoneSessionKey: ,openIdSessionKey: ,timeStamp: , }, //10位时间戳(秒)…...
提升视觉回归测试体验:Cypress 插件推荐
项目介绍 在现代前端开发中,视觉回归测试是确保用户界面在不同版本之间保持一致性的关键步骤。然而,传统的视觉回归测试工具往往复杂且难以使用。为了解决这一问题,我们推荐一款专为 Cypress 设计的插件:Cypress Plugin Visual Re…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
Linux基础开发工具——vim工具
文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...
「Java基本语法」变量的使用
变量定义 变量是程序中存储数据的容器,用于保存可变的数据值。在Java中,变量必须先声明后使用,声明时需指定变量的数据类型和变量名。 语法 数据类型 变量名 [ 初始值]; 示例:声明与初始化 public class VariableDemo {publi…...
