channelinactive触发后不关闭channel_go那些事儿|channel使用及其实现原理

目录 

  • channel背景

  • channel基本用法

  • channel应用场景

  • channel实现原理

    • channel数据结构

    • channel实现方式

  • channel注意事项

  • 闲聊

  • 欢迎加入我的公众号【迈莫coding】 一起pk大厂

1channel背景

channel是Go的核心类型,是Go语言内置的类型,你无需引包,就能使用它。你可以把它看作一个管道,在Go语言中流传着一句话,"执行业务处理的goroutine不要通过共享内存通信,要通过channel管道进行共享数据"

channel和Go的另一种特性goroutine一起为并发编程提供了优雅的,便利的方案,来应对并发场景。

2channel基本用法

channel的基本用法非常简单,它提供了三种类型,分别为只能接收只能发送既能接收也能发送这三种类型。因此它的语法为:

chanstruct{} chan chan string // 既能接收也能发送

我们把既能发送也能接收的chan被称为双向chan,把只能接收或者只能发送的chan称为单向chan。其中,"这个箭头总是射向左边的,元素类型总在最右边。如果箭头指向 chan,就表示可以往 chan 中塞数据;如果箭头远离 chan,就表示 chan 会往外吐数据。

通过make关键字,我们可以初始化一个chan,未初始化的chan的零值为nil。你可以设置他的容量,第二个参数为缓冲池的容量大小,也可以理解为即使chan未消费完,也可以存储数据。

make(chan int, 8)
 

如果chan中还有数据,那么从这个chan中接收数据就不会阻塞,如果chan中数据未达到队列容量,那么向该chan中存储数据也不会阻塞,反之会阻塞。

还有一个知识点要记住:nil 是 chan 的零值,是一种特殊的 chan,对值是 nil 的 chan 的发送接收调用者总是会阻塞。

接下来,我们用代码来学习一下chan的三种类型

  • 只能接收数据的chan

代码示例

package main import "fmt"// a 表示只能接收数据的chanfunc goChanA(a chan int) {  b :=   fmt.Println("只能接收数据的channal[a]接收到的数据值为", b)}func main() {  ch := make(chan int, 2)  go goChanA(ch)  // 往ch中写入数据值  ch 2  time.Sleep(time.Second)}

结果

只能接收数据的channal[a]接收到的数据值为 2
 
  • 只能发送数据的chan

代码示例

package main import "fmtfunc main() {  ch := make(chan  ch }

往 chan 中发送一个数据使用“ch

这里的 ch 是 chan int 类型或者是 chan

3channel应用场景

  • 数据交流:当作并发的 buffer 或者 queue,解决生产者 - 消费者问题。多个 goroutine 可以并发当作生产者(Producer)和消费者(Consumer)。

  • 数据传递:一个goroutine将数据交给另一个goroutine,相当于把数据的拥有权托付出去。

  • 信号通知:一个goroutine可以将信号(closing,closed,data ready等)传递给另一个或者另一组goroutine。

  • 任务编排:可以让一组goroutine按照一定的顺序并发或者串行的执行,这就是编排功能。

  • 锁机制:利用channel实现互斥机制。

4channel实现原理

channel数据结构

channel一个类型管道,通过它可以在goroutine之间发送消息和接收消息。它是golang在语言层面提供的goroutine间的通信方式。

众所周知,Go依赖于称为CSP(Communicating Sequential Processes)的并发模型,通过 Channel实现这种同步模式。 

channel结构体

//path:src/runtime/chan.gotype hchan struct {  qcount uint          // 当前队列列中剩余元素个数  dataqsiz uint        // 环形队列长度,即可以存放的元素个数  buf unsafe.Pointer   // 环形队列列指针  elemsize uint16      // 每个元素的⼤⼩  closed uint32        // 标识关闭状态  elemtype *_type      // 元素类型  sendx uint           // 队列下标,指示元素写⼊入时存放到队列列中的位置 x  recvx uint           // 队列下标,指示元素从队列列的该位置读出    recvq waitq          // 等待读消息的goroutine队列  sendq  waitq         // 等待写消息的goroutine队列  lock mutex           // 互斥锁,chan不允许并发读写}

从数据结构可以看出channel由队列、类型信息、goroutine等待队列组成。       

channel实现方式

chan内部实现了一个缓冲队列作为缓冲区,队列的长度是创建chan时指定的。

下图展示了可缓存6个元素的channel示意图:

64d45f6d3923fdda3d340b4497b4e36a.png

  • dataqsiz:指向队列的长度为6,即可缓存6个元素

  • buf:指向队列的内存,队列中还剩余两个元素

  • qcount:当前队列中剩余的元素个数

  • sendx:指后续写入元素的位置

  • recvx:指从该位置读取数据

等待队列

从channel中读数据,如果channel缓冲区为空或者没有缓冲区,当前goroutine会被阻塞;向channel中写数据,如果channel缓冲区已满或者没有缓冲区,当前goroutine会被阻塞。

被阻塞的goroutine将会被挂在channel的等待队列中:

  • 因读阻塞的goroutine会被向channel写入数据的goroutine唤醒

  • 因写阻塞的goroutine会被从channel读数据的goroutine唤醒

下面展示了一个没有缓冲区的channel,有几个goroutine阻塞等待数据:

0fdb36a14ce7d88223749c7d3bf990d3.png

注意,一般情况下recvq和sendq至少有一个为空。只有一个例外,那就是同一个goroutine使用select语句向channel一边写数据一边读数据。

向channel写数据

  • 流程图:

86e83d00c8ac28899200226f51871608.png

  • 详细过程

    • 如果recvq队列不为空,说明缓冲区没有数据或者没有缓冲区,此时直接从recvq等待队列中取出一个G,并把数据写入,最后把该G唤醒,结束发送过程;

    • 如果缓冲区有空余位置,则把数据写入缓冲区中,结束发送过程;

    • 如果缓冲区没有空余位置,则把数据写入G,将当前G写入sendq队列,进入休眠,等待被读goroutine唤醒;

从channel读数据

  • 流程图

d163599fbb3bd7e9daf87a61562069f0.png

  • 详细过程

    • 如果等待发送队列sendq不为空,且没有缓冲区,直接从sendq队列中取出G,把G中数据读出,最后把G唤醒,结束读取过程;

    • 如果等待发送队列sendq不为空,说明缓冲区已满,从缓冲队列中首部读取数据,从sendq等待发送队列中取出G,把G中的数据写入缓冲区尾部,结束读取过程;

    • 如果缓冲区中有数据,则从缓冲区取出数据,结束读取过程;

5channel注意事项
  • 向已经关闭的channel中写入数据会发生Panic

  • 关闭已经关闭的channel会发生Panic

  • 关闭值为nil的channel会发生Panic

6闲聊

  • 读完文章,自己是不是和channel管道的cp率又提高了

  • 我是迈莫,欢迎大家和我交流

原创不易,觉得文章写得不错的小伙伴,点个赞? 鼓励一下吧~

7欢迎加入我的公众号【迈莫coding】 一起pk大厂

  • 迈莫coding欢迎客官的到来

c71cb360c98bf6eb4b13a2f1c7b9935b.png

68ccefea8c1c3fb7b132f83ccc9b8973.png

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

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

相关文章

matlab画信号频谱

为了让大学生活充实一点,多学点东西,我选修了《数字信号处理》。现在充实得不要不要的。 clc close all clear%参数设置% Fs 1000; % Sampling frequency T 1/Fs; % Sampling period L 1500; …

关于字节序(大端法、小端法)的定义

关于字节序(大端法、小端法)的定义《UNXI网络编程》定义:术语“小端”和“大端”表示多字节值的哪一端(小端或大端)存储在该值的起始地址。小端存在起始地址,即是小端字节序;大端存在起始地址,即是大端字节序。 也可以说&#xff…

html div初始隐藏点击可见_3种CSS3移动手机隐藏菜单UI界面代码解析/附源码下载...

这是一款效果非常酷的jQuery和CSS3移动手机隐藏菜单UI界面设计。这个UI设计共有三种不同的打开隐藏菜单的效果,分别为滑动显示,Material Design风格效果和展开式效果。使用方法HTML结构这三种不同的隐藏菜单的HTML结构大致基本相同。第一种滑动效果菜单的…

《数据结构与抽象:Java语言描述(原书第4版)》一P.4.1 标识类

本节书摘来华章计算机《数据结构与抽象:Java语言描述(原书第4版)》一书中的第1章 ,[美]弗兰克M.卡拉诺(Frank M. Carrano) 蒂莫西M.亨利(Timothy M. Henry) …

【SVM】简单介绍(一)

1、结构风险最小化 我们想要在未知的数据上得到低的错误率&#xff0c;这叫做structural risk minimization;相对的&#xff0c;训练误差叫做empirical risk minimization 要是我们能有这样一个式子就好了&#xff1a; Test error rate <train error rate f(N,h,p)\text {…

L8_2

4.留下pid为12345的那个sh进程&#xff0c;杀死系统中所有其它sh进程 ps –ef|grep sh |awk ‘{if($2!”12345”) {print “kill “$2}}’ >killpid.sh cat killpid.sh ./killpid.sh 5. 根据以下日志文件&#xff0c;计算使用各种浏览器的人所占的百分比&#xff08;注意先排…

# 遍历删除字典元素_第六章 字典

一、使用字典一个简单的字典字典是一系列键——值对。每个键都与一个值相关联&#xff0c;可以使用键来访问与之相关联的值。与键相关联的值可以是数字、字符串、列表乃至字典。事实上&#xff0c;可将任何Python对象用作字典中的值。在Python中&#xff0c;字典用放在花括号{}…

【SVM】简单介绍(二)

1、SVM另一种推法 我们不管分类平面&#xff0c;直接去假设Margin的两个边界&#xff1a; Plus-plane {x:w⋅xb1}Minus-plane {x:w⋅xb−1}\begin{aligned} & \text { Plus-plane }\{\boldsymbol{x}: \boldsymbol{w} \cdot \boldsymbol{x}b1\} \\ & \text { Minus-plan…

图像像素点赋值_Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像...

普通操作1. 读取像素读取像素可以通过行坐标和列坐标来进行访问&#xff0c;灰度图像直接返回灰度值&#xff0c;彩色图像则返回B、G、R三个分量。需要注意的是&#xff0c; OpenCV 读取图像是 BGR 存储显示。灰度图片读取操作&#xff1a;import cv2 as cv# 灰度图像读取gray_…

cocopods

一、什么是CocoaPods 1、为什么需要CocoaPods 在进行iOS开发的时候&#xff0c;总免不了使用第三方的开源库&#xff0c;比如SBJson、AFNetworking、Reachability等等。使用这些库的时候通常需要&#xff1a; 下载开源库的源代码并引入工程向工程中添加开源库使用到的framework…

CSS3学习手记(10) 过渡

CSS3过渡 允许css的属性值在一定的时间内平滑地过渡在鼠标单击、获取焦点、被点击或对元素任何改变中触发&#xff0c;并圆滑地以动画效果改变CSS的属性值transition transition-property属性检索或设置对象中的参与过渡的属性 语法 transition-property:none|all|property …

全局搜索快捷键_Windows 自带的聚合搜索来了,与 Mac 的 Spotlight 相比体验如何?...

最近 Windows 10 推出了自带的聚合搜索功能 PowerToys Run&#xff0c;取代了之前的 WinR。苹果的 macOS 以人性化著称&#xff0c;有几个功能让 Windows 用户一直很羡慕&#xff0c;比如全局的聚合搜索工具 Spotlight。在任何界面 command空格&#xff0c;输入关键字就能搜索电…

【SVM】简单介绍(三)

我们考虑SVM的对偶问题&#xff0c;我们通常是在对偶空间中进行求解的。 1、Lagrange Multipliers 对于一个很一般的问题 Minimize f(x)subject to {a(x)≥0b(x)≤0c(x)0\begin{aligned} \text { Minimize } & f(x) \\ \text { subject to } \quad & \left\{\begin{a…

寻找白板上的便签条

问题来源&#xff1a;http://answers.opencv.org/question/162480/contour-detection-for-gray-stickers-on-white-background/ 题目的大概意思就是这样的白板&#xff0c;寻找上面的各种便签条。我找到了橘色的&#xff0c;结果是这样代码是这样Mat src imread("gray-st…

gg

转载于:https://www.cnblogs.com/lyzuikeai/p/7091206.html

HDU 1728 逃离迷宫

这道题做的我想哭啊。。WA了将近十次了吧 一开始我用数组模拟的队列&#xff0c;后来和老大代码对拍&#xff0c;感觉改的是基本都一模一样了&#xff0c;还是WA 实在没有办法了&#xff0c;改用queue了 题目里的x是列y是行&#xff0c;和代码里的反过来的&#xff0c;要注意&a…

Nginx(六)-- 配置文件之Gzip

1.概念及作用 Gizp主要对内容、静态文件做压缩&#xff0c;用来提升网站访问速度&#xff0c;节省带宽。 2.使用方法 gzip既可以配置在server中&#xff0c;也可以配置在server外&#xff0c;此处配置在server中&#xff0c;如下&#xff1a; 说明&#xff1a;  gizp on|off 是…

误码率越高越好还是越低越好_夜间护理步骤越多越好还是越少越好?NFF

现在很多人都知道了夜晚是护肤的黄金护肤时间&#xff0c;有些很聪明的姐妹就从夜晚着手&#xff0c;使用很多种护肤品&#xff0c;希望达到事半功倍的效果&#xff0c;但好皮肤不常有&#xff0c;皮肤问题却常有&#xff01;既然如此&#xff0c;不少人就问了&#xff0c;夜间…

【随机森林】random forests 简单介绍

Random Forest&#xff0c;顾名思义 Random 就是随机抽取&#xff1b; Forest 就是说这里不止一棵树&#xff0c;而由 一群决策树组成的一片森林 &#xff0c;连起来就是用随机抽取的方法训练出一群决策树来完成分类任务。RF用了两次随机抽取, 一次是对训练样本的随机抽取; 另一…

信息安全系统设计基础第三周学习总结—20135227黄晓妍

一.Vim编辑器 1.Vim的六种模式 2.Vim三种常用模式的使用方式&#xff0c;以及三者的切换。打开Vim即默认进入普通模式&#xff0c;按i进入插入模式&#xff0c;按esc从插入模式退出普通模式&#xff0c;再按&#xff1a;进入命令行模式。 普通模式下游标的移动 按键 说明 h …