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 可以作用于管道,如果遍历的管道没有关闭,则会将管道中的所有的元素遍历并取出,并阻塞读取管道中的元素;如果遍历的是一个已经关闭的管道,则会取出管道中的所有的元素,并正常关闭。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

内网安全[3]-代理Socks协议路由不出网后渗透通讯CS-MSF控制上线

1.环境 隧道技术: 隧道技术是一类网络协议,它是一种数据包封装技术,它将原始IP包(其报头包含原始发送者和最终目的地)封装在另外一个数据包(称为封装的IP包)的数据净荷中进行传输,使用隧道的原…

V4和V6双栈处理

现进行双栈 对R1 对R2 对R3 对R4 路由地址配完,起协议 然后起ripng,在R2,R3,R4上都宣告一下 然后在PC1和PC2上都手动配置一下就可以了

第1章 MySQL数据库概述

1.1 基本概念 数据库是什么? 存储数据的地方 DB:数据库(Database) 为什么要用数据库? 因为应用程序产生的数据是在内存中的,如果程序退出或者是断电了,则数据就会消失。使用数据库是为了…

CVPR上新 | 从新视角合成、视频编解码器、人体姿态估计,到文本布局分析,微软亚洲研究院精选论文

编者按:欢迎阅读“科研上新”栏目!“科研上新”汇聚了微软亚洲研究院最新的创新成果与科研动态。在这里,你可以快速浏览研究院的亮点资讯,保持对前沿领域的敏锐嗅觉,同时也能找到先进实用的开源工具。 本周&#xff0…

DLS平台:美联储松绑预期升温,金价飙升至2365美元

摘要 美联储鹰派官员古尔斯比对降息态度有所松动,导致金价一度升至2365美元。市场对美联储未来的货币政策预期有所改变,黄金作为避险资产的吸引力增强。本文将详细分析美联储官员态度变化对金价的影响、当前市场对黄金的预期及其未来走势。 美联储官员态…

Spring Boot中的各种事件

spring boot 各种事件贯穿整个启动的生命周期,读懂了这些事件也差不多理解了springboot的启动流程。 SpringApplicationRunListener中的事件 接口org.springframework.boot.SpringApplicationRunListener定义了spring启动过程中各个事件被触发的顶层方法 public …

JavaScript的学习之强制类型转换

目录 一、什么是强制类型转换 二、其他类型转化为String类型 方式一:调用被转化数据类型的toString()方法 方式二:调用String函数,并将我们要转换的数据添加进去为参数 三、其他类型转化为Number类型 方式一:使用Number()函数…

Python有哪些就业方向?就业市场广阔!

Python是一种跨平台的计算机程序设计语言,是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。Python语言在人工智能的发展下,越来越多计算机企业开始广泛使用,同时Python的就业方向也逐渐广阔。 YesPMP为学习Python的技术人员…

【环境变量问题:计算机删除环境变量的恢复方法;此环境变量太大。此对话框允许将值设置为最长2047个字符】

不小心误删了win10系统环境变量可以试试下文方法恢复。 本方法针对修改环境变量未重启的用户可以使用,如果修改环境变量,然后还重启了,只能说重新来。 方法一:使用命令提示符恢复 被修改的系统Path只是同步到了注册表中&#x…

QListWidget、QMenu、Action、customContextMenuRequested

QListWidget的初始化、清空、Append添加、Insert添加、删除item QListWidget的事件的使用 QToolBox的使用,每个Page可以添加其他控件 QToolBar使用代码添加QMenu,QMenu添加3个Action QToolButton绑定Action 布局 其中 QSplitter比较特殊, 允许在水平或垂…

策略模式:applicationContext.getBeansOfType()方法

applicationContext.getBeansOfType() 一般用来获取某个接口的所有实例Bean 方法定义如下: 入参一般是接口,即interface。响应是个Map结构,key bean在容器中的名称,value bean实列 开发步骤: 1.定义接口 2.定义…

NGINX_十八 nginx 访问控制

十八 nginx 访问控制 1 nginx 访问控制模块 (1)基于IP的访问控制:http_access_module (2)基于用户的信任登录:http_auth_basic_module 2 基于IP的访问控制 2.1 配置语法 Syntax:allow addr…

kettle从入门到精通 第七十二课 ETL之kettle 三谈http post(含文件上传),彻底掌握参数传递

场景:群里有个小伙伴在使用http post步骤调用接口时遇到问题,postman调用正常,但是kettle中调用异常。 解决方案:既然postman调用接口正常,肯定是http post步骤中某些参数设置的不正确导致的。那就把常用的方式都梳理下…

C++11 右值引用和移动语义

目录 1.左值引用和右值引用 2.右值引用使用场景(移动语义)和意义 3.右值引用引用左值及其一些更深入的使用场景分析 4.完美转发 1.左值引用和右值引用 传统的C语法中就有引用的语法,而C11中新增了的右值引用语法特性,所以从现…

云计算考试题

Cloud ❀ 云计算-虚拟化常见的两种架构_裸金属架构和宿主型架构的区别-CSDN博客 为啥要成2 11 bcd 16 acd abcd BCD NAS为啥支持文件存储的协议 选BCD 什么是网络文件系统 选bcd 错题 选abc 选bcd 选 abd

【ARMv8/v9 GIC 系列 4.2 -- GIC CPU Interface 详细介绍】

文章目录 GIC CPU Interface 介绍CPU Interface 主要寄存器 GIC CPU Interface 介绍 A 系列处理器提供 5个管脚来实现中断,分别是: nIRQ:物理普通中断nFIQ:物理快速中断nVIRQ:虚拟普通中断nVFIQ:虚拟快速…

运算放大器(运放)积分器电路

积分器电路 运算放大器(运放)积分器电路是在图2运放反相放大器的电路上增加一个积分电容构成,该积分电容并联在运算放大器的反馈电阻上,见图1。 运算放大器(运放)反相放大器电路 设计目标 输入fMin输入f0dB输入fMax输出VoMin输出VoMax电源Vcc电源Vee1…

【JS重点19】this指向问题总结

目录 一:普通函数this指向 普通函数在严格模式下: 二:箭头函数this指向 this指向说明 不适用this情况 三:改变this指向 1 call() 语法格式: 作用: 2 apply() 语法格式: 作用&#x…

C#.net6.0语言+B/S架构+前后端分离 手术麻醉信息管理系统源码

C#.net6.0语言+B/S架构前后端分离 手术麻醉信息管理系统源码 什么是手术麻醉信息管理系统 满足医院等级评级需求 满足电子病历评级需求 满足科室需求 术前 1、患者术前评估/诊断 2、术前讨论制定手术方案 3、手术准备 4、术前准备 术中 1、送手术室 2、麻…

oracle12c到19c adg搭建(五)dg搭建后进行切换19c进行数据字典升级

一、备库切主库升级 12c切换为19c主库的时候是由低版本到高版本所以cdb和pdb的数据字典需要进行升级才可以让数据与软件版本兼容。 1.1切换 SQL> alter database recover managed standby database finish; Database altered. SQL> alter database commit to switcho…