Go 的 Buffered Channel 的阻塞机制
在Go语言中,有一种特殊的通道类型叫做Buffered Channel(缓冲通道),它在通道中储存一定数量的元素。当通道中的元素数量达到设定的上限时,写入操作会被阻塞住,直到有其他协程从通道中读取元素。相反,当通道中的元素数量为零时,读取操作也会被阻塞住,直到有其他协程向通道中写入元素。这种阻塞机制可以有效地控制协程之间的同步和通信。在本文中,我们将详细介绍Go语言中Buffered Channel的阻塞机制。
问题内容
在《Tour of Go》中,示例代码是这样给出的:
package main import "fmt" func main() { ch := make(chan int, 2) ch <- 1 ch <- 2 fmt.Println(<-ch) fmt.Println(<-ch) }
它执行良好并打印出来
1 2
此行为与此练习的描述不同,其中指出:
<code> Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty </code>
在 ch <- 2
行之后,ch
is 已满,并且由于我们只运行 1 个单独的 Goroutine,即主 Goroutine,因此该 Goroutine 应该被阻塞,直到 ch
is 被接收者消耗,因此代码不应该到达fmt.Println(<-ch)
行,但应该说类似
<code> fatal error: all goroutines are asleep - deadlock! </code>
但是,由于情况并非如此,我很困惑,并寻求指导。
这是我写的另一段代码
chh := make(chan int, 2) go func() { chh <- 1 fmt.Printf("chh after 1: %v, %v\n", cap(chh), len(chh)) chh <- 2 fmt.Printf("chh after 2: %v, %v\n", cap(chh), len(chh)) chh <- 3 fmt.Printf("chh after 3: %v, %v\n", cap(chh), len(chh)) }() fmt.Println(<-chh) fmt.Println(<-chh) fmt.Println(<-chh)
执行结果为
1 chh after 1: 2, 0 chh after 2: 2, 0 chh after 3: 2, 1 2 3
这更令人困惑。这次有另一个 goroutine 进行发送。我的期望是,在第一个 fmt.Println(<-chh)
期间,主 goroutine 应该被阻塞。调度程序将选择运行匿名函数的 goroutine,并且它应该执行到 chh <- 2
,然后它会阻塞自身,调度程序再次恢复到主 goroutine。然而,如结果所示,第二个 goroutine 在 chh <- 1
之后立即被阻塞。为什么会这样?
编辑: 我仍然不明白为什么我的本地首先打印 1 。当我在远程服务器上尝试使用 go Playground 时,它显示出不同的行为,现在与我的期望一致。
已知channel是由3个队列组成(接收goroutines、发送goroutines ans value buffer),当匿名函数运行时,channel chh
的状态为(sending:empty,valuebuffer:empty,receiving:[main] )
。
正在运行的子 Goroutine 只是将值直接推入主 Goroutine,而没有实际将其传递到值缓冲区。这就是为什么chh
推送后1
的长度是0
。
解决方法
该通道可容纳两人。两次发送可以成功而不会阻塞。 第三个不能。仅当通道在发送之前已满时,发送才会阻塞。
以上是Go 的 Buffered Channel 的阻塞机制的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

Go语言中用于浮点数运算的库介绍在Go语言(也称为Golang)中,进行浮点数的加减乘除运算时,如何确保精度是�...

Go爬虫Colly中的Queue线程问题探讨在使用Go语言的Colly爬虫库时,开发者常常会遇到关于线程和请求队列的问题。�...

Go语言中哪些库是大公司开发或知名开源项目?在使用Go语言进行编程时,开发者常常会遇到一些常见的需求,�...

Go语言中结构体定义的两种方式:var与type关键字的差异Go语言在定义结构体时,经常会看到两种不同的写法:一�...

Go语言中字符串打印的区别:使用Println与string()函数的效果差异在Go...

Go语言中使用RedisStream实现消息队列时类型转换问题在使用Go语言与Redis...

Go指针语法及viper库使用中的寻址问题在使用Go语言进行编程时,理解指针的语法和使用方法至关重要,尤其是在...

为什么Go语言中的map迭代会导致所有值变成最后一个元素?在Go语言中,面对一些面试题时,经常会遇到关于map�...
