Jje*_*jed 7 concurrency go goroutine
作为一个愚蠢的基本线程练习,我一直在尝试在golang中实现睡眠理发师问题.有了频道,这应该很容易,但我遇到了一个heisenbug.也就是说,当我尝试诊断它时,问题就消失了!
考虑以下.该main()函数将整数(或"客户")推送到shop通道上.barber()读取shop频道以削减"顾客"的头发.如果我fmt.Print在customer()函数中插入一个语句,程序将按预期运行.否则,barber()永远不要削减任何人的头发.
package main
import "fmt"
func customer(id int, shop chan<- int) {
// Enter shop if seats available, otherwise leave
// fmt.Println("Uncomment this line and the program works")
if len(shop) < cap(shop) {
shop <- id
}
}
func barber(shop <-chan int) {
// Cut hair of anyone who enters the shop
for {
fmt.Println("Barber cuts hair of customer", <-shop)
}
}
func main() {
shop := make(chan int, 5) // five seats available
go barber(shop)
for i := 0; ; i++ {
customer(i, shop)
}
}
Run Code Online (Sandbox Code Playgroud)
知道正在发生什么吗?
问题是Go的调度程序的实现方式.只有在进行系统调用或阻塞通道操作时,当前goroutine才能产生其他goroutine.fmt.Println进行系统调用,给goroutine一个屈服的机会.否则它没有.
在实践中,这通常并不重要,但对于像这样的小问题,它有时会突然出现.
此外,在频道上进行非阻塞发送的更惯用,更少生动的方式是:
func customer(id int, shop chan<- int) {
// Enter shop if seats available, otherwise leave
select {
case shop <- id:
default:
}
}
Run Code Online (Sandbox Code Playgroud)
你这样做的方式,客户可能最终会在理发店外等待,因为当你实际发送邮件时,len(shop)可能已经改变了.
| 归档时间: |
|
| 查看次数: |
1170 次 |
| 最近记录: |