Golang容器:Channel

Channel概念

Channel管道 是Go语言中一种强大的通信机制,它使得在并发运行的goroutines之间可以高效地交换数据。通过Channel管道,goroutines能够:

  • 同步执行:Channel管道可以用来协调并发任务的执行顺序,确保它们在正确的时间点上执行。
  • 数据共享:与传统的共享内存模型不同,Channel管道提供了一种通过通信来共享数据的方式,这有助于避免竞态条件和锁的复杂性。
  • 消息队列:Channel管道可以作为消息队列使用,允许goroutines发送和接收消息,实现生产者-消费者模式。
  • 线程同步:Channel管道还可以作为线程同步的工具,用于控制线程间的协作和通信。

Channel使用

创建

msgChan:=make(chan int)
masgChan:=make(chan int,100)

chan分为有缓冲区,无缓冲区

有缓冲区:可以向里面写数据,也可以读数据,只有缓冲区满了写操作才会阻塞,当缓冲空了读操作才会阻塞

无缓冲区:只有读操作就绪才能写入数据,否则都是阻塞着的,实现同步。也就是说,发送的数据需要被读取后,发送才会完成

读写操作

使用“< -”操作符,变量位置不同表示不同操作

//向chan中写数据
msgChan<-i
//读取chan中的shuj
i:=<-MsgChan

操作符“<-”标识了数据的流向,处于箭头指向的一方可以看作数据的流入方;反之,则为数据流出方。当channel为流入方时,代表向channel中写入数据;反之,则代表从channel中读取数据。

channel实现原理

Chanel的数据结构是hchan

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          // 通道的锁
}

buf用来存储,dataqsiz表示缓冲区大小,当一个协程向channel写入数据,如果未有足够的空间吧容纳,会被加入sendq队列中,被阻塞的接收数据的协程会加入recvq队列

type waitq struct {first *sudog //队列头部last  *sudog //队列尾部
}

写数据的过程

  1. 数据准备:在发送方的协程中准备要发送的数据
  2. 首先检查recvq有没有正在等待读取的协程。如果有,就代表没有缓冲区或者缓冲区中没有数据,那么,就从recvq中拿出第一个协程,数据交由该协程处理,然后激活该协程
  3. 如果recvq没有阻塞的协程,则尝试将数据写入缓冲区
  4. 如果没有缓冲区,或者缓冲区已满,则阻塞该协程,并将协程对象加入sendq中

读取数据的过程

  1. 首先检查sendq是否为空,如果不为空,且没有缓冲区,那么就从sendq中获取第一个协程,并复制其数据,然后激活该协程、
  2. 如果sendq不为空,但有缓冲区,那么就从缓冲区中获取数据
  3. 如果sendq为空。同样要尝试从缓冲区中获取数据,如果不能读取数据,则将自己加入recvq中

整体

Chanel各种操作导致阻塞和协程泄露的场景

写操作

  1. 向nil通道发送数据会被阻塞
  2. 向无缓冲channel写数据,如果读协程没有准备好,会阻塞
  3. 无缓冲channel,必须要有读有写,有数据后必须读出来,否则导致channel阻塞,从而使协程阻塞导致协程泄露
  4. 向有缓冲的chanel写数据,如果缓冲已满,会阻塞

读操作

  1. 从nil通道接收数据会被阻塞
  2. 从无缓冲channel读取数据,如果写协程没有准备好,会被阻塞
  3. 从有缓冲channel读数据,如果缓冲为空会阻塞

向已关闭的Channel发送或者读取数据都会发生错误

协程泄露情况

  1. 协程未关闭channel

    如果一个协程创建Channel但没有正确关闭,并且其他协程尝试从中读取或者写入数据,这都会导致死锁和协程泄露

  2. 协程等待永远不会发送的数据

    如果一个协程正在Channel上等待数据,而发送数据的协程已经结束或者阻塞,这多可能导致等待的协程永远无法继续执行

  3. 错误的channel关闭

    不恰当的时机关闭Channel,例如仍有协程等待数据时关闭Channel

  4. 协程在Channel上无限期阻塞

    如果Channel的发送或接收操作没有适当的超时或退出机制,协程可能无限期阻塞在Channel上

  5. 协程未处理Channel关闭

    在读取Channel时Channel已经关闭,但没有相应地退出循环或逻辑,这可能导致goroutine泄露。

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

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

相关文章

String类型的二维数组怎么写

今天做题遇到一个问题&#xff1a;就是需要写String类型的二维数组时&#xff0c;我蒙圈了。后来查了资料发现&#xff0c;String类型的二维数组其实是由若干个一维数组构成的。 1.先初始化一个二维数组&#xff1a;List<List<String>> list new ArrayList<&g…

centos7.9安装docker

安装docker yum install docker -y 安装 docker-compose sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-linux-x86_64" -o /usr/local/bin/docker-composechmod x /usr/local/bin/docker-compose mysql docker-com…

基于JAVA+SpringBoot+Vue前后端分离的医院在线挂号预约问诊平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 链接点击直达&#xff1a;下载链接 前言 哈喽兄弟…

前端Vue小兔鲜儿电商项目实战Day05

一、登录 - 整体认识和路由配置 1. 整体认识 登录页面的主要功能就是表单校验和登录退出业务 ①src/views/Login/index.vue <script setup></script><template><div><header class"login-header"><div class"container m-…

springboot 后端文件上传,多文件上传,预览接口开发实现

在Spring Boot中实现文件上传和多文件上传的功能可以通过使用Spring MVC的MultipartFile类来实现。以下是一个简单的示例代码,展示了如何实现文件上传和多文件上传的功能。 首先,创建一个用于处理文件上传请求的Controller类。在该类中,我们需要使用@PostMapping注解来接收…

Gitee的原理及应用详解(四)

本系列文章简介&#xff1a; Gitee是一款开源的代码托管平台&#xff0c;是国内最大的代码托管平台之一。它基于Git版本控制系统&#xff0c;提供了代码托管、项目管理、协作开发、代码审查等功能&#xff0c;方便团队协作和项目管理。Gitee的出现&#xff0c;在国内的开发者社…

Re0:从零开始的C++游戏开发【上】

Re0:从零开始的C游戏开发 这是蒟蒻观看B站upVoidmatrix的课程从零开始的提瓦特幸存者的个人笔记【自用】 前言&#xff1a;采用适用于小白的easyx图形库。 第一集 追着鼠标的小球 #include <graphics.h> #include <iostream> int main(void) {// 初始化initgra…

微信小程序教程DAY3

box标签 第二种方法 绿色第一种 第一种更好 效果一样 完成这个项目 先写循环

Python深度学习基于Tensorflow(13)目标检测实战

文章目录 RPN 整体代码RPN 具体实现过程数据标注读取标注数据固定图片大小调整目标框使用预训练模型获取 feature_shape定义 RPN 网络生成RPN 的 CLS 和 REG 数据集获取所有的锚点计算锚点与目标框的IOU 定义 RPN loss 和 训练过程 参考资料 这里实现的是二阶段目标检测&#x…

十分钟快速搭建检索、排序的大模型RAG系统

以上为实现效果 RAG是目前最火的大模型应用之一&#xff0c;如何能快速实现一个不错的demo呢&#xff1f; 参考 https://github.com/LongxingTan/open-retrievalshttps://colab.research.google.com/drive/1fJC-8er-a4NRkdJkwWr4On7lGt9rAO4P?uspsharing#scrollTo2Hrfp96UY…

第二届“天洑杯”全国高校数据建模大赛圆满收官

近日&#xff0c;第二届“天洑杯”全国高校数据建模大赛在江苏省无锡市第七届智能优化与调度学术会议现场圆满收官。在为期四周的线上赛中&#xff0c;共有来自全国 71 所高校及企业的 117 支队伍参与角逐&#xff0c;共10支队伍进入决赛。 本届大赛评审组由西安电子科技大学教…

鸿蒙开发接口媒体:【@ohos.multimedia.camera (相机管理)】

相机管理 说明&#xff1a; 开发前请熟悉鸿蒙开发指导文档&#xff1a; gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 本模块首批接口从API version 9开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块…

Vue3实战笔记(52)—Vue 3封装持仓分析饼图

文章目录 前言一、封装持仓分析饼图总结 前言 接上文&#xff0c;封装持仓分析饼图。 一、封装持仓分析饼图 EChartsPieBorderRadiusType.vue&#xff1a; <template><div><div ref"chartContainer" style"width: 100%; height: 450px"&g…

vue中使用pinia实现状态管理——useXXXStore函数

vue中使用pinia实现状态管理 大家一定在vue中还见过 useXXXStore这样的函数&#xff0c;用来实现状态管理的。可以把它当成一个永远存在的组件&#xff0c;每个组件都可以读取和写入它。它有三个概念&#xff0c;state、getter 和 action&#xff0c;我们可以假设这些概念相当…

低边驱动与高边驱动

一.高边驱动和低边驱动 低边驱动(LSD): 在电路的接地端加了一个可控开关&#xff0c;低边驱动就是通过闭合地线来控制这个开关的开关。容易实现&#xff08;电路也比较简单&#xff0c;一般由MOS管加几个电阻、电容&#xff09;、适用电路简化和成本控制的情况。 高边驱动&am…

Qt 窗口

在Qt Creator 中创建项目的时候&#xff0c;我们能够选择创建QMainWindow 还是 QWidget 两种窗口。 二者有什么区别呢&#xff1f;其中 QMainWindow 是一种主窗口&#xff0c;包含菜单栏&#xff0c;工具栏&#xff0c;状态栏&#xff0c;中心窗口和浮动窗口等多个窗口组合&…

Java基础学习: 代理模式(Proxy Pattern)

文章目录 一、简介1、介绍2、代理模式在Java中的应用 二、实现方式1、静态代理2、动态代理 三、动态代理1、JDK2、Cglib3、总结 参考 一、简介 1、介绍 代理模式 2、代理模式在Java中的应用 统一异常处理。Mybatis使用了代理。Spring aop实现代理。日志框架。 二、实现方式…

位置参数

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 位置参数也称必备参数&#xff0c;是必须按照正确的顺序传到函数中&#xff0c;即调用时的数量和位置必须和定义时是一样的。 &#xff08;1&#x…

使用 Docker 和 Docker Compose 部署 Vue

使用 Docker 和 Docker Compose 部署 Vue 项目有两种方式&#xff1a;直接使用 Docker 和使用 Docker Compose。 创建 Dockerfile 在Vue.js项目根目录下创建一个 Dockerfile 的文件 # 使用最新的官方 Node.js 镜像作为基础镜像&#xff0c;并命名为 builder 阶段 FROM node:…

内测:ew0.0版本

温馨提示&#xff1a;懒得编&#xff0c;可能会存在一点点bug。 合作请私信我&#xff0c;周六日有空。 合作对象&#xff1a;小学生&#xff0c;初中生不等。 #include<bits/stdc.h> #include<windows.h> using namespace std; void sprintf(string s){int len…