[Go]通道(channel)的基本操作
通道类型是Go语言自带的、唯一一个可以满足并发安全性的类型,在声明并初始化一个通道时,需要用到内建函数make,传给make函数的第一个参数应该代表通道的具体类型的类型字面量。
如类型字面量 chan int,其中chan表示通道类型的关键字,而int说明了该通道类型的元素类型。
在初始化通道时,make函数除了必须接受这样的字面量作为参数,还可以接收一个int类型的参数。后者是可选的,用于表示通道的容量(通道最多缓存多少个元素值),不能小于0。当容量为0时称其为非缓冲通道,当容量大于0时,可以称为缓冲通道
一个通道相当于一个先进先出(FIFO)的队列。元素值的发送和接收都需要用到操作符 <-
package main import "fmt" func main() {
ch1 := make(chan int, )
ch1 <-
ch1 <-
ch1 <-
elem1 := <-ch1
fmt.Printf("first element :%v\n", elem1)
}
由于该通道容量为3,所以可以在通道不包含任何元素值的时候,连续地向该通道发送三个值,此时这三个值都会被缓存在通道之中。当从通道接收元素值的时候,同样要用接送操作符 <-
1、对通道的发送和接收操作都有哪些基本的特性?
1)对于同一个通道,发送操作之间是互斥的,接收操作之间也是互斥的
在同一时刻,Go语言的运行时系统只会执行对同一个通道的任意个发送操作中的某一个,知道这个元素值被完全复制进该通道之后,其他针对该通道的发送操作才可能被执行
类似的,在同一时刻,运行时系统也只会执行对同一个通道的任意个接收操作中的某一个,直到这个元素值完全被移除该通道之后,其他针对该通道的接收操作才可能被执行。
另外,对于通道中的同一个元素值来说,发送操作和接收操作也是互斥的,虽会出现正在被复制进通道但还未复制完成的元素值,但此时它绝不会被想接收它的一方看到和取走
并且,元素值从外界进入通道时会被复制,进入通道的并不是接收操作符右边那个元素值,而是它的副本。
2)发送操作和接收操作中对元素值的处理都是不可分割的
不可分割的意思是处理元素值时是一气呵成不会被打断的
发送操作要么还没复制元素值,要么已经复制完毕,绝不会出现只复制一部分的情况
接收操作在准备好元素值的副本之后,一定会删除通道中的原值,绝不会出现通道中仍有残留的情况
对于通道中的桶一个元素值来说,它只可能是某一个发送操作放入的,同时也只可能被某一个接收操作取出
3)发送操作在完成之前会被阻塞,接收操作也是
发送操作包括“复制元素值”和“放置副本通道内部”两个步骤,在这两个步骤完全完成之前,发起这个发送操作的那句代码会一直阻塞在那里,在它之后的代码不会有执行的机会,直到这句代码阻塞解除。在通道完成发送操作之后,运行时系统会通知这句代码所在 的goroutine,以使它去争取继续运行代码的机会
接收操作包括“复制通道内的元素”,“放置副本到接收方”,“删掉原值”三个步骤,同理在这些步骤完全完成之前,发起该操作的代码也会一直阻塞。
2、发送操作和接收操作在什么时候可能被长时间阻塞
1)缓冲通道
如果通道已满,那么对它的所有发送操作都会被阻塞,直到通道中有元素值被接收走。通道会优先通知最早等待的那个发送操作所在的goroutine,通知的顺序总是公平的
如果通道已空,那么对它的所以接收操作都会被阻塞,直到通道中有新的元素值出现,通道会优先通知最早等待的那个接收操作所在的goroutine,通知的顺序总是公平的
2)非缓冲通道
无论发送操作还是接收操作,一开始执行就会被阻塞,直到配对的操作也开始执行。即非缓冲通道是在用同步的方式传递数据,也就是说,只有收发双方对接上了,数据才会被床底,数据是直接从发送方复制到接收方的,中间并不会用非缓冲通道做中转
3)对值为nil的通道
不论它的具体类型是什么,对它的发送操作和接收操作都会永久地处于阻塞状态,它们所属的goroutine中的任何代码,都不会被执行。因此一定要初始化通道
3、发送操作和接收操作在什么时候会引发panic?
对于一个已初始化,但并未关闭的通道来说,收发操作一定不会引发panic,但通道一旦关闭,再对它进行发送操作,就会引发panic。
如果试图关闭一个已经关闭了的通道,也会引发panic
当把接收表达式结果同时赋值给两个变量时,第二个变量的类型就是一定bool类型,它的值如果是False就说明通道已经关闭,并且再没有元素值可取。如果通道关闭时,里面还有元素值未被取出,那么接收表达式的第一个结果仍会是通道中的某一个元素值,而第二个结果值一定会是true
[Go]通道(channel)的基本操作的更多相关文章
- nio再学习之通道channel
通道(Channel):用于在数据传输过程中,进行输入输出的通道,其与(流)Stream不一样,流是单向的,在BIO中我们分为输入流,输出流,但是在通道中其又具有读的功能也具有写的功能或者两者同时进行 ...
- Java NIO中的通道Channel(一)通道基础
什么是通道Channel 这个说实话挺难定义的,有点抽象,不过我们可以根据它的用途来理解: 通道主要用于传输数据,从缓冲区的一侧传到另一侧的实体(如文件.套接字...),反之亦然: 通道是访问IO服务 ...
- NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件
通道(Channel) 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channe ...
- 理解CNN中的通道 channel
在深度学习的算法学习中,都会提到 channels 这个概念.在一般的深度学习框架的 conv2d 中,如 tensorflow .mxnet ,channels 都是必填的一个参数. channel ...
- go中的数据结构通道-channel
1. channel的使用 很多文章介绍channel的时候都和并发揉在一起,这里我想把它当做一种数据结构来单独介绍它的实现原理. channel,通道.golang中用于数据传递的一种数据结构.是g ...
- 详解 通道 (Channel 接口)
在本篇博文中,本人主要讲解NIO 的两个核心点 -- 缓冲区(Buffer) 和 通道 (Channel)之一的 缓冲区(Buffer), 有关NIO流的其他知识点请观看本人博文<详解 NIO流 ...
- Java NIO之通道Channel
channel与流的区别: 流基于字节,且读写为单向的. 通道基于快Buffer,可以异步读写.除了FileChannel之外都是双向的. channel的主要实现: FileChannel Data ...
- go实例之轻量级线程goroutine、通道channel与select
1.goroutine线程 goroutine是一个轻量级的执行线程.假设有一个函数调用f(s),要在goroutine中调用此函数,请使用go f(s). 这个新的goroutine将与调用同时执行 ...
- Java-NIO(四):通道(Channel)的原理与获取
通道(Channel): 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Chann ...
- Java NIO中的通道Channel(二)分散/聚集 Scatter/Gather
什么是Scatter/Gather scatter/gather指的在多个缓冲区上实现一个简单的I/O操作,比如从通道中读取数据到多个缓冲区,或从多个缓冲区中写入数据到通道: scatter(分散): ...
随机推荐
- 使用VMwaver 克隆CentOS 6.9网卡配置报错
报错信息: 克隆完成之后,使用的是NAT模式,进入系统之后有IP地址也可以ping外网,但是没有ifcfg-eth0这个文件,使用setup命令配置网卡时报以下错误: 待解决-
- Unity3D中GameObject 详细介绍
通过Hierarchy面板下的Create菜单可以手动地创建一个GameObject,它可以是一个相机,一个灯光,或者一个简单的模型,当我们要在程序里面动态地创建一个相机的时候,可以new一个Game ...
- 享元模式及php实现
享元模式: 享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用.系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用.由于享元模式要求 ...
- iOS 解决iOS 9下的http请求发送失败问题
iOS9中 因为系统要求所有的请求都必须使用https, 所以发送http请求会失败,如果想让程序能够兼容http请求 在info.plist中添加以下代码: 这里需要做的是右键info.plist文 ...
- Failure to transfer org.apache.maven.plugins:maven-compiler-plugin:jar:2.5.1
Mac上写了一段基于Maven的java代码. 上传Git后,在windows上pull下来,eclipse里面各种错误. ArtifactTransferException:Failure to t ...
- LR 两种录制:html与url
一直在使用LR,对于Html_based script和Url-based script 两种录制方式之间,要如何选择,仍是一知半解.最近测试时遇到同样的业务功能,两种录制方式的脚本,单次执行时间差别 ...
- 如何使用capedit分割数据包文件
wireshark是一个网络数据包的分析工具,主要用来捕获网卡上的数据包并显示数据包的详细内容.在处理一些大的数据包文件时,如果直接用wireshark图形工具打开一些大文件的数据包会出现响应慢甚至没 ...
- django URL,views,html请求顺序
进来的请求转入/hello/. Django通过在ROOT_URLCONF配置来决定根URLconf. Django在URLconf中的所有URL模式中,查找第一个匹配/hello/的条目 ...
- 【转】C#的版本
这年头啥东东都喜欢过段时间整个啥新版本出来.汽车,手机如此,软件就更是如此了啊.比如啥Iphone 4,Iphone 5,Windows 8,Oracle 12C,SQL Server 2010. 版 ...
- Selenium3+python自动化008-操作浏览器基本方法
一.打开网站1.第一步:从selenium里面导入webdriver模块2.打开Firefox浏览器(Ie和Chrome对应下面的)3.打开百度网址二.页面刷新1.有时候页面操作后,数据可能没及时同步 ...