内容简介:声明一个通常的基本语法:当容量为0时,我们可以称通道为非缓冲通道,当容量大于0时,我们称为缓冲通道;一个通道相当于一个先进先出(FIFO)的队列。也就是说,通道中的各个元素都是严格地按照发送的顺序排列的,先被发送通道的元素值一定会先被接受。元素值的发送和接受都需要用到操作符<-。我们也可以叫它接受操作符。
声明一个通常的基本语法: channel := make(chan int,0)
当容量为0时,我们可以称通道为非缓冲通道,当容量大于0时,我们称为缓冲通道;
一个通道相当于一个先进先出(FIFO)的队列。也就是说,通道中的各个元素都是严格地按照发送的顺序排列的,先被发送通道的元素值一定会先被接受。元素值的发送和接受都需要用到操作符<-。我们也可以叫它接受操作符。
问:对通道的发送和接受操作都有哪些基本特性?
答: 1.对于同一个通道,发送操作之间是互斥的,接受操作之间也是互斥的。
2.发送操作和接受操作中对元素值的处理都是不可分割的。
3.发送操作在完全完成之前都会被阻塞。接受操作也是如此。
第一个特性:在同一时刻,Go语言的运行时系统只会执行对同一个通道的任意个发送操作中的一个。
直到这个元素被完全复制进该通道之后,其针对该通道的发送操作才可能被执行。
类似的,在同一时刻,运行时系统也只会执行,对同一通道的任意个接受操作中的某一个。
直到这个元素完全被移出该通道之后,其他针对该通道的接受操作才可能被执行。即使这些操作是并发执行的也是如此。
另外,对于通道中的同一个元素来说,发送操作和接受操作之间也是互斥的。例如:虽然会出现,正在被复制进通道但还未复制完成的元素值,但是这是它绝不会被想接受它的一方看到和取走。
细节:元素值从外界进入通道是会被复制。更具体地说,进入通道的并不是接受操作符右边的那个元素值,而是它的副本。
第二个特性:发送操作要么还没复制元素值,要么以及复制完成,绝不会出现复制一部分的情况。这个操作是原子性的。
这既是为了保证通道中元素值的完整性,也是为了保证通道操作的唯一性。对于通道中的同一个元素值来说,它只可能是某一个发送操作放入的,同时也只可能被某一个接受操作取出。
第三个特性:一般情况下,发送操作包括了 "复制元素值" 和 "放置副本到通道内部" 这两个步骤。
在这两个步骤完成前,发起这个操作的那句代码及grountine会一直阻塞。
另外,接受操作也包括了 "复制通道内的元素" 和 "放置副本到接收方" , "删除原值" 这三个步骤。
在这些步骤完全完成前,发起该操作的代码及grountine会一直阻塞。
如此阻塞代码其实就是为了实现操作的互斥和元素值的完整。
问题:发送操作和接受操作在什么时候可能被长时间的阻塞?
答:对于缓冲通道来说。如果通道已满,那么对它的所有发送操作都会被阻塞,直到通道内有元素值被接受走。
这是, 通道会优先通知最早因此而等待的、那个发送操作所在的goroutine ,因为发送操作被阻塞后,它们所在的goroutine会顺序地进入通道内部的发送等待队列;
接受等待情况也是如此,同样也有接受等待队列。
对于非缓冲通道,无论是发送操作还是接受操作,一开始执行就会被阻塞,直到配对的操作开始执行。
在大多数情况下,缓冲通道都会作为收发双方的中间件。元素值会先从发送方复制到缓冲通道,之后再有缓冲通道复制到接收方。但是,当发送操作正在执行的时候发现空的通道中,正好有等待的接受操作,那么它会直接把元素值复制给接收方。
对于值为nil的通道,不论它的具体类型是什么,对它的发送操作和接受操作都会永久处于阻塞状态。
问题:发送操作和接受操作在什么时候引发panic?
1.对一个已关闭的channel 进行发送操作,会引发panic
2.关闭一个已经关闭了的channel,会引发panic
注意:接受操作是可以感知到通道关闭的,并能够安全退出。当我们把接受表达式的结构同时赋值给两个变量时,第二个值为false代表通道已经关闭,并且没有元素可取。
如果通道关闭时,里面还有元素未被取出,那么接受表达式的第二个结果一定是true。因此,通过表达式的第二个结果,判断通道是否关闭具有延时性。
注:通道长度代表通道当前包含的元素个数。
以上所述就是小编给大家介绍的《golang 通道channel 基础》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Go基础-channel通道
- Golang 并发,有缓存通道,通道同步案例演示
- 科普 | 菜鸟学习状态通道,Part-2:App 定制型状态通道
- golang通道定义
- 通道 | Java NIO
- Go 通道
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。