go之无缓冲channel(通道)和有缓冲channel(通道)
channel
我们先来看一下通道的解释:
channel是Go语言中的一个核心类型,可以把它看成管道。并发核心单元通过它就可以发送或者接收数据进行通讯,这在一定程度上又进一步降低了编程的难度。
channel是一个数据类型,主要用来解决go程的同步问题以及协程之间数据共享(数据传递)的问题。
goroutine运行在相同的地址空间,因此访问共享内存必须做好同步。goroutine 奉行通过通信来共享内存,而不是共享内存来通信。
引用类型 channel可用于多个 goroutine 通讯。其内部实现了同步,确保并发安全。
定义channel和使用
和map类似,channel也一个对应make创建的底层数据结构的引用。
当我们复制一个channel或用于函数参数传递时,我们只是拷贝了一个channel引用,因此调用者和被调用者将引用同一个channel对象。和其它的引用类型一样,channel的零值也是nil。
定义一个channel时,也需要定义发送到channel的值的类型。channel可以使用内置的make()函数来创建:
我们先来看一段代码
package main
import "fmt"
func main(){
ch:=make(chan int) //这里就是创建了一个channel,这是无缓冲管道注意
go func(){ //创建子go程
for i:=0;i<6;i++{
ch<-i //循环写入管道
fmt.Println("写入",i)
}
}()
for i:=0;i<6;i++{ //主go程
num:=<-ch //循环读出管道
fmt.Println("读出",num)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
我们先看一下运行结果再来看代码:
我们在代码中 先创建了一个匿名函数的子go程,和main的主go程一起争夺cpu,但是我们在里面创建了一个管道,无缓冲管道有一个规则那就是必须读写同时操作才会有效果,如果只进行读或者只进行写那么会被阻塞,被暂时停顿等待另外一方的操作,在这里我们定义了一个容量为0的通道,这就是无缓冲通道,如下图
无缓冲通道就是这样,一次只能传输一个数据
总结一下就是无缓冲特性:
同一时刻,同时有 读、写两端把持 channel。
如果只有读端,没有写端,那么 “读端”阻塞。
如果只有写端,没有读端,那么 “写端”阻塞。
读channel: <- channel
写channel: channel <- 数据
有缓冲channel
如图所示:
. 在第 1 步,右侧的 goroutine 正在从通道接收一个值。
在第 2 步,右侧的这个 goroutine独立完成了接收值的动作,而左侧的 goroutine 正在发送一个新值到通道里。
在第 3 步,左侧的goroutine 还在向通道发送新值,而右侧的 goroutine 正在从通道接收另外一个值。这个步骤里的两个操作既不是同步的,也不会互相阻塞。
最后,在第 4 步,所有的发送和接收都完成,而通道里还有几个值,也有一些空间可以存更多的值。
有缓冲通道就是图中所示,一方可以写入很多数据,不用等对方的操作,而另外一方也可以直接拿出数据,不需要等对方写,但是注意一点(如果写入的一方把channel写满了,那么如果要继续写就要等对方取数据后才能继续写入,这也是一种阻塞,读出数据也是一样,如果里面没有数据则不能取,就要等对方写入),而有缓冲channel定义也比较简单
ch:=make(chan int,10)//chan int 只能写入读入int类型的数据,10代表容量为10.
1
这里用了自动推导类型来声明了一个有缓冲的channel
总结起来就是:
channel 中自带缓冲区。创建时可以指定缓冲区的大小。
w:直到缓冲区被填满后,写端才会阻塞。
r:缓冲区被读空,读端才会阻塞。
len:代表缓冲区中,剩余元素个数,
cap:代表缓冲区的容量。
在这里可以举个小小的例子来解释一下有缓冲channel和无缓冲channel
同步通信: 数据发送端,和数据接收端,必须同时在线。 —— 无缓冲channel
打电话。打电话只有等对方接收才会通,要不然只能阻塞
异步通信:数据发送端,发送完数据,立即返回。数据接收端有可能立即读取,也可能延迟处理。 —— 有缓冲channel 不用等对方接受,只需发送过去就行
发信息。短信。
是不是很形象呢
下一节将讲解一下channel常见的陷阱以及关闭channel
————————————————
版权声明:本文为CSDN博主「sgsgy5」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sgsgy5/article/details/82054902
go之无缓冲channel(通道)和有缓冲channel(通道)的更多相关文章
- Halcon学习之三:有关图像通道的函数(R是三通道,B是1通道,G二通道),排列顺序BGR
黑白摄像机会返回每个像素所对应的能量采用结果,这些结果组成了一幅单通道灰度值图像,而对于RGB彩色摄像机,它将返回每个像素所对应的三个采样结果,也就是一幅三通道图像.下面这些是与图像通道有关的函数: ...
- Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'me
在启动RabbitMQ消费端的时候报错:Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol ...
- STM32F10x_ADC三通道DMA连续转换(3通道、软件单次触发)
Ⅰ.概述 上一篇文章讲述的内容是:三通道逐次转换(单次.单通道软件触发),也就是说3条通道要三次软件触发才能完成转换,而且是通过软件读取转换数值. 本文讲述三通道DMA连续转换(3通道.软件单次触发) ...
- 使用opencv为没有透明通道的图像加入透明通道
在图像处理中,我们经常需要处理带透明通道的图片,比如为图片或视频添加水印,为图片或视频添加字幕.贴图等.然而,我们的素材图片未必总是带有透明通道.比如,素材的背景本该透明的地方,却是黑色和白色.有时, ...
- 标准I/O缓冲:全缓冲、行缓冲、无缓冲
说明:我仅仅对网络资源进行了整合,方便学习-.- 基于流的操作终于会调用read或者write函数进行I/O操作.为了使程序的执行效率最高,流对象一般会提供缓冲区,以降低调用系统I/O库函数的次数. ...
- EasyNVR摄像机网页Chrome无插件视频播放功能二次开发之通道配置文件上传下载示例代码
背景需求 熟悉EasyNVR产品的朋友们都知道,产品设计初期根据整个直播流程层级,我们将EasyNVR无插件直播系统划分为:硬件层.能力层.应用层,连接硬件与应用之间的桥梁,同时屏蔽各种厂家硬件的不同 ...
- cell下载图片的思路 --无沙盒(内存)缓冲
// // ViewController.m // 06-表格图片下载 // // Created by jerry on 15/9/7. // Copyright (c) 2015年 jerry. ...
- EasyNVR无插件直播服务器软件使用详情功能-通道配置Excel
背景需求 使用EasyNVR的用户都有知道,由于EasyNVR是将设备与EasyNVR的通道进行绑定的,因此EasyNVR是通过手动的通道配置来进行设备接入的,这样可以做到将设备的和通道对应的接入.但 ...
- [bigdata] flume file channel CPU消耗比 memory channel高的原因
https://www.quora.com/Why-does-flume-take-more-resource-CPU-when-file-channel-is-used-compared-to-wh ...
随机推荐
- Vue-Cli项目如何查看依赖调用关系?
Vue是个优秀的前端框架,不管是前端还是后端开发人员都能很快使用Vue来开发应用.但是随着项目开发的深入,组件之间的依赖就变得越来越多,耦合越来越严重.这时候我们迫切地需要分析下组件和依赖之间的调用关 ...
- JavaMaven【七、插件使用】
配置pom.xml 配置在那个周期的那个阶段执行该插件的功能 上图是配置了使用插件source3.0.1,该插件的功能是打包源码 并配置了在package阶段后执行打包源码的操作jar-no-fork ...
- navicat连接阿里云mysql
1.服务器控制台在安全组配置3306端口 2.进入 /etc/ssh/sshd_config 在最下面 加入下面代码 KexAlgorithms diffie-hellman-group1-sha1, ...
- centos nginx https 配置
1,如果想配置一个域名到指定目录咋弄呢?下面这个 server { listen ; server_name 这里换成你的域名,例如baidu.com; set $root_path '/home/w ...
- C++——函数
C++基础函数 (一)函数的参数传递 在没有调用函数之前,函数的形参并没有占据实际的空间. 1.值传递 传入的仅仅只是一个值--就是把实参的值赋给形参.形参自己会在内存中开辟一个空间! 2.传引用 这 ...
- python zip用法
import requests url = "https://magi.com/search" querystring = {"q":"堕却乡&quo ...
- NoSQL数据库技术实战-第1章 NoSQL与大数据简介 NoSQL产生的原因
NoSQL产生的原因: 关系型数据库不擅长的操作,是NoSQL应运而生的原因: 大量的数据写入操作书上写的是“大量数据的写入操作“,我理解的应该是“大量的数据写入操作”,因为大量的数据写入操作才会引起 ...
- java 实现链表
public class MyList { Entry head; class Entry { Object data; Entry next; public Entry(Object data) { ...
- java 面试题摘要
5.1 什么是线程 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程的实际运作单位, 可以使用多线程对运算提速. 5.2 线程和进程有什么区别 (1)进程是资源的分配和调度的一个独 ...
- Python-multiprocessing-Process模块
获取当前执行该文件的进程ID import os # 获取当前执行该文件的进程ID print("Process (%s) start..." % os.getpid()) mul ...