通道

用途

不要通过共享内存来通信,要通过通信来共享内存。后通道就是后半句的完美实现。

特点

go自带的唯一一个支持并发安全的数据类型。

一个通道相当于一个先进先出(FIFO)的队列。也就是说,通道中的各个元素值都是严格地按照发送的顺序排列的,先被发送通道的元素值一定会先被接收。

类型

缓冲通道

非缓冲通道

todo:底层实现?

通道的发送和接收特点

对于同一个通道,发送操作之间是互斥的,接收操作之间也是互斥的(并发安全)。

发送操作和接收操作中对元素值的处理都是不可分割的(支持原子性)。

发送操作在完全完成之前会被阻塞。接收操作也是如此。

发送过程

发送操作包括了“复制元素值”和“放置副本到通道内部”这两个步骤。

接收过程

接收操作通常包含了“复制通道内的元素值”“放置副本到接收方”“删掉原值”三个步骤。

todo:底层实现?

发送操作和接收操作在什么时候可能被长时间的阻塞?

先说针对缓冲通道的情况。如果通道已满,那么对它的所有发送操作都会被阻塞,直到通道中有元素值被接收走。这时,通道会优先通知最早因此而等待的、那个发送操作所在的 goroutine,后者会再次执行发送操作。

由于发送操作在这种情况下被阻塞后,它们所在的 goroutine 会顺序地进入通道内部的发送等待队列,所以通知的顺序总是公平的。

相对的,如果通道已空,那么对它的所有接收操作都会被阻塞,直到通道中有新的元素值出现。这时,通道会通知最早等待的那个接收操作所在的 goroutine,并使它再次执行接收操作。因此而等待的、所有接收操作所在的 goroutine,都会按照先后顺序被放入通道内部的接收等待队列。

对于非缓冲通道,情况要简单一些。无论是发送操作还是接收操作,一开始执行就会被阻塞,直到配对的操作也开始执行,才会继续传递。

由此可见,非缓冲通道是在用同步的方式传递数据。也就是说,只有收发双方对接上了,数据才会被传递。并且,数据是直接从发送方复制到接收方的,中间并不会用非缓冲通道做中转。相比之下,缓冲通道则在用异步的方式传递数据。在大多数情况下,缓冲通道会作为收发双方的中间件。正如前文所述,元素值会先从发送方复制到缓冲通道,之后再由缓冲通道复制给接收方。

但是,当发送操作在执行的时候发现空的通道中,正好有等待的接收操作,那么它会直接把元素值复制给接收方。

通道的底层实现

todo:环形链表

单向通道

单向发通道 make(chan<- int)

单向收通道 make(<-chan int)

单向通道作用

约束(入参和出参)

获取元素

for

select

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值