go Channel原理 (四)

news2024/10/7 4:31:23

Channel

设计原理

不要通过共享内存的方式进行通信,而是应该通过通信的方式共享内存。

在主流编程语言中,多个线程传递数据的方式一般都是共享内存。
在这里插入图片描述
Go 可以使用共享内存加互斥锁进行通信,同时也提供了一种不同的并发模型,即通信顺序进程(Communicating sequential processes,CSP)。Goroutine 和 Channel 分别对应 CSP 中的实体和传递信息的媒介,Goroutine 之间会通过 Channel 传递数据。在这里插入图片描述
上图中的两个 Goroutine,一个会向 Channel 中发送数据,另一个会从 Channel 中接收数据,它们两者能够独立运行并不存在直接关联,但是能通过 Channel 间接完成通信。

关闭 channel

func closechan(c *hchan) {
   // 关闭一个 nil channel,panic
   if c == nil {
      panic(plainError("close of nil channel"))
   }

   // 上锁
   lock(&c.lock)
   // 如果 channel 已经关闭
   if c.closed != 0 {
      unlock(&c.lock)
      // panic
      panic(plainError("close of closed channel"))
   }

   // …………

   // 修改关闭状态
   c.closed = 1

   var glist *g

   // 将 channel 所有等待接收队列的里 sudog 释放
   for {
      // 从接收队列里出队一个 sudog
      sg := c.recvq.dequeue()
      // 出队完毕,跳出循环
      if sg == nil {
         break
      }

      // 如果 elem 不为空,说明此 receiver 未忽略接收数据
      // 给它赋一个相应类型的零值
      if sg.elem != nil {
         typedmemclr(c.elemtype, sg.elem)
         sg.elem = nil
      }
      if sg.releasetime != 0 {
         sg.releasetime = cputicks()
      }
      // 取出 goroutine
      gp := sg.g
      gp.param = nil
      if raceenabled {
         raceacquireg(gp, unsafe.Pointer(c))
      }
      // 相连,形成链表
      gp.schedlink.set(glist)
      glist = gp
   }

   // 将 channel 等待发送队列里的 sudog 释放
   // 如果存在,这些 goroutine 将会 panic
   for {
      // 从发送队列里出队一个 sudog
      sg := c.sendq.dequeue()
      if sg == nil {
         break
      }

      // 发送者会 panic
      sg.elem = nil
      if sg.releasetime != 0 {
         sg.releasetime = cputicks()
      }
      gp := sg.g
      gp.param = nil
      if raceenabled {
         raceacquireg(gp, unsafe.Pointer(c))
      }
      // 形成链表
      gp.schedlink.set(glist)
      glist = gp
   }
   // 解锁
   unlock(&c.lock)

   // Ready all Gs now that we've dropped the channel lock.
   // 遍历链表
   for glist != nil {
      // 取最后一个
      gp := glist
      // 向前走一步,下一个唤醒的 g
      glist = glist.schedlink.ptr()
      gp.schedlink = 0
      // 唤醒相应 goroutine
      goready(gp, 3)
   }
}
  1. 关闭状态 closed 值为 1。
  2. 将 recvq 和 sendq 中所有正在阻塞的 gorountine 唤醒。sender 直接 panic,receiver 返回一个相应类型的零值。

channel 的使用,有几点不方便的地方:
3. 在不改变 channel 自身状态的情况下,无法获知一个 channel 是否关闭。
4. 关闭一个 closed channel 会导致 panic。
5. 向一个 closed channel 发送数据会导致 panic。

由于关闭一个 cloed 的 channel 或者由 sender 关闭 channel 会导致panic,所以关闭 channel 应该是:
6. channel 不手动关闭由 gc 代劳。
7. 由 sender 关闭并确保只关闭一次(比如 sync.Once)。

channel 发送和接收元素的本质

All transfer of value on the go channels happens with the copy of value.

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

channel 在什么情况下会引起资源泄漏

channel 可能会引发 goroutine 泄漏。
泄漏的原因是 goroutine 操作 channel 后,处于发送或接收阻塞状态,而 channel 处于满或空的状态,一直得不到改变。同时,垃圾回收器也不会回收此类资源,进而导致 gouroutine 会一直处于等待队列中。
程序运行过程中,对于一个 channel,如果没有任何 goroutine 引用了,gc 会对其进行回收操作,不会引起内存泄漏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1887104.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

终极指南:RNNS、Transformers 和 Diffusion 模型

一、说明 作为广泛使用这些工具和模型的人,我的目标是解开 RNN、Transformer 和 Diffusion 模型的复杂性和细微差别,为您提供详细的比较,为您的特定需求提供正确的选择。 无论您是在构建语言翻译系统、生成高保真图像,还是处理时间…

【ACM出版,马来西亚-吉隆坡举行】第四届互联网技术与教育信息化国际会议 (ITEI 2024)

作为全球科技创新大趋势的引领者,中国不断营造更加开放的科技创新环境,不断提升学术合作的深度和广度,构建惠及各方的创新共同体。这是对全球化的新贡献,是构建人类命运共同体的新贡献。 第四届互联网技术与教育信息化国际学术会议…

【CSAPP】-binarybomb实验

目录 实验目的与要求 实验原理与内容 实验设备与软件环境 实验过程与结果(可贴图) 操作异常问题与解决方案 实验总结 实验目的与要求 1. 增强学生对于程序的机器级表示、汇编语言、调试器和逆向工程等方面原理与技能的掌握。 2. 掌握使用gdb调试器…

【ONLYOFFICE】| 桌面编辑器从0-1使用初体验

目录 一. 🦁 写在前面二. 🦁 在线使用感受2.1 创建 ONLYOFFICE 账号2.2 编辑pdf文档2.3 pdf直接创建表格 三. 🦁 写在最后 一. 🦁 写在前面 所谓桌面编辑器就是一种用于编辑文本、图像、视频等多种自媒体的软件工具,具…

.NET周刊【6月第5期 2024-06-30】

国内文章 呼吁改正《上海市卫生健康信息技术应用创新白皮书》 C# 被认定为A 组件 的 错误认知 https://www.cnblogs.com/shanyou/p/18264292 近日,《上海市卫生健康“信息技术应用创新”白皮书》发布,提到医疗信创核心应用适配方法及公立医院信息系统…

thinksboard新建table表格

html文件 <div fxFlex fxLayoutAlign"left top" style"display: block"> <!-- <mat-card appearance"raised" style"max-height: 80vh; overflow-y: auto;">--><div><button mat-raised-button (click)&…

linux和mysql基础指令

Linux中nano和vim读可以打开记事文件。 ifdown ens33 ifup ens33 关闭&#xff0c;开启网络 rm -r lesson1 gcc -o code1 code1.c 编译c语言代码 ./code1 执行c语言代码 rm -r dir 删除文件夹 mysql> show databases-> ^C mysql> show databases; -------…

基于STM32的卫星GPS路径记录仪

目录 引言环境准备卫星GPS路径记录仪基础代码实现&#xff1a;实现卫星GPS路径记录仪 4.1 数据采集模块4.2 数据处理与分析4.3 存储系统实现4.4 用户界面与数据可视化应用场景&#xff1a;路径记录与分析问题解决方案与优化收尾与总结 1. 引言 卫星GPS路径记录仪通过使用STM…

第十四届蓝桥杯省赛C++B组A题【日期统计】题解(AC)

题目大意 给定的字符串中&#xff0c;有几个子序列是 2023 2023 2023 年的日期&#xff08;每个日期只能算一次&#xff09;。 法一 枚举所有长度为 8 8 8 的子序列&#xff0c;判断是否是有效日期并去重&#xff0c;时间复杂度 O ( C 100 8 ) O(C^8_{100}) O(C1008​)。…

秋招Java后端开发冲刺——并发篇1(线程与进程、多线程)

一、进程 1. 进程 进程是程序的一次动态执行过程&#xff0c;是操作系统资源分配的基本单位。 2. 进程和线程的区别 特性进程线程定义独立运行的程序实例&#xff0c;资源分配的基本单位进程中的一个执行单元&#xff0c;CPU调度的基本单位资源进程拥有独立的内存空间和资源线…

Java_多线程:线程池

1、线程池优点&#xff1a; 降低资源消耗&#xff1a;通过重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度&#xff1a;当任务到达时&#xff0c;任务可以不需要等到线程创建就能立即执行。提高线程的可管理性&#xff1a;线程是稀缺资源&#xff0c;如果无限…

c语言的烫烫烫烫烫??

当初学习C语言时&#xff0c;对于一些特殊的打印输出可能会感到困惑&#xff0c;比如会出现一堆乱码烫烫烫的情况。其实这是因为在C语言中&#xff0c;对于字符类型和数字类型之间的隐式转换可能会导致打印输出的结果不符合预期。这并不意味着程序员"烫"&#xff0c;…

鸿蒙开发Ability Kit(程序访问控制):【安全控件概述】

安全控件概述 安全控件是系统提供的一组系统实现的ArkUI组件&#xff0c;应用集成这类组件就可以实现在用户点击后自动授权&#xff0c;而无需弹窗授权。它们可以作为一种“特殊的按钮”融入应用页面&#xff0c;实现用户点击即许可的设计思路。 相较于动态申请权限的方式&am…

Dify入门指南

一.Dify介绍 生成式 AI 应用创新引擎&#xff0c;开源的 LLM 应用开发平台。提供从 Agent 构建到 AI workflow 编排、RAG 检索、模型管理等能力&#xff0c;轻松构建和运营生成式 AI 原生应用&#xff0c;比 LangChain 更易用。一个平台&#xff0c;接入全球大型语言模型。不同…

Google地图获取位置的前端代码与测试

test.html <script src"http://maps.google.com/maps/api/js?sensorfalse"></script> <script > if (navigator.geolocation) {  console.log(Geolocation is supported!);// var startPos;var geoSuccess function(position) {startPos p…

MySQL4(事务、函数、慢查询和索引)

目录 一、MySQL事务 1. 概念 2. 事务的ACID原则 3. MySQL实现事务的方法 4. MySQL实现事务的步骤 5. 事务的原子性、一致性、持久性 6. 事务的隔离性 7. MySql中的锁 1. 共享锁 2. 排他锁 3. 行级锁 4. 表级锁 5. 间隙锁 6. 临键锁 7. 记录锁 8. 意向共享锁…

236、二叉树的最近公共祖先

前提&#xff1a; 所有 Node.val 互不相同 。p ! qp 和 q 均存在于给定的二叉树中。 代码如下&#xff1a; class Solution { public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if (root q || root p || root NULL) return root;TreeN…

赛灵思FFT的IP核——非实时模式 Non real time

一、IP核配置 使用非实时模式配置如下 二、时序 是遵守AXIS协议的&#xff0c;不像real time mode&#xff0c;一旦开始吭哧吭哧的读数据&#xff0c;根本不管s_axis_data_tvalid信号了。 三、资源消耗 在implement查看两者的资源消耗差不多 四、仿真 4.1 中间不停顿 输入…

uniapp微信接口回调 response.sendRedirect nginx 报404错误

如题 参考 uniapp打包H5时,访问index.html页面白屏报错net::ERR_ABORTED 404 - 简书 nginx中修改 配置文件 location / { try_files $uri $uri/ /index.html; root html; index index.html index.htm; } uniapp里配置 重新载入

js,uni 自定义 时间选择器 vue2

<template><view class"reserve-time-box"><view class"title">选择时间</view><view class"date-box"><view class"date-scroll-box" :style"{ width : ${dataTimeWidth}rpx }"><v…