golang的channel浅析

简介

channel是golang的一个重要特性,可用于goroutine同步和通信,channel基于共享内存实现,具有FIFO特性。

chan的分类

//read and write
chan
//write only
chan<-
//read only
<-chan

此外还可以分为有缓冲无缓冲chan。

无缓冲chan

无缓冲chan,没有缓冲队列,其读写两端需要同步,否之阻塞。可用于goroutine之间的同步操作。

创建无缓冲chan:

ch := make(chan int)
//or: ch := make(chan int, 0)
var rch <-chan int = ch
var wch chan<- int = ch
带缓冲chan

带缓冲的chan有缓冲队列,chan的生产者和消费者可以异步读写,不过再chan缓冲满时写阻塞,在chan的缓冲为空时读阻塞。

创建带缓冲chan:

ch := make(chan int, 20)
var rch <-chan int = ch
var wch chan<- int = ch

其他

迭代chan

可以使用for-range来迭代chan,chan关闭自动退出循环。

for value := range ch {
	//todo...
}

panic

在chan关闭后的读写会产生panic。

屏蔽panic:

val, ok := <-ch
//ok's type is bool

使用ok状态来检查chan是否关闭。

非阻塞

对于无缓冲的chan,只有阻塞读写。

对于有缓冲的chan,可以进行非阻塞读写操作。

首先在缓冲区未满的写,缓冲区未空的读都是非阻塞的。

在缓冲未空的读和缓冲满的写的非阻塞操作
  1. 使用time.timer来进行定时操作,超时退出。(伪的)

  2. 使用len和cap对chan进行测试,然后读写。

    https://golang.google.cn/pkg/builtin/#len

关于chan的线程安全问题

这里将线程安全定义为多个goroutine同时读写一个chan。

chan的读写是线程安全的。

实现原理

【有待填坑】

https://zhuanlan.zhihu.com/p/62391727
https://my.oschina.net/renhc/blog/2246871

在 Go 中,可以使用 channel 实现限流,即通过 channel 的容量控制并发执行的协程数。 示例代码如下: ```go package main import ( "fmt" "time" ) func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Printf("worker %d 执行任务 %d\n", id, j) time.Sleep(time.Second) // 模拟任务执行时间 results <- j * 2 } } func main() { jobs := make(chan int, 100) // 创建任务 channel,缓冲区大小为 100 results := make(chan int, 100) // 创建结果 channel,缓冲区大小为 100 // 创建 3 个 worker 协程,即最多同时执行 3 个任务 for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // 发送 9 个任务到 jobs channel for j := 1; j <= 9; j++ { jobs <- j } close(jobs) // 关闭 jobs channel,表示所有任务已发送完毕 // 收集所有结果 for a := 1; a <= 9; a++ { <-results } } ``` 在上面的示例中,我们创建了一个 `jobs` channel 和一个 `results` channel,用于分别传递任务和结果。我们创建了 3 个 worker 协程,并将 `jobs` 和 `results` channel 分别传递给它们。在主协程中,我们向 `jobs` channel 发送 9 个任务,并关闭 `jobs` channel,表示所有任务已发送完毕。然后我们收集所有结果。 由于 `jobs` channel 的缓冲区大小为 100,即最多可以存储 100 个任务,而 `results` channel 的缓冲区也为 100,即最多可以存储 100 个结果。因此,当 worker 协程数小于等于 3 时,所有任务都可以立即执行;当 worker 协程数大于 3 时,多余的任务会被存储在 `jobs` channel 中,直到有空闲的 worker 协程可以执行它们。这样就实现了限流的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值