作为一个愚蠢的基本线程练习,我一直在尝试在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)
}
}
知道发生什么了吗?
问题是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:
}
}
您这样做的方式是,客户可能最终在理发店外面等了,因为到您实际进行发送时,len(shop)
可能已经改变了。
问题内容: 我的程序中有多个goroutine,每个goroutine都进行调用而没有任何显式同步。这样安全吗(即,每行将单独出现而不会破坏数据),还是我需要创建另一个带有同步的goroutine来专门处理打印? 问题答案: 不,即使您有时可能没有发现任何麻烦,也不安全。IIRC,fmt软件包试图处于安全状态,因此可能会发生某种混合,但希望不会导致进程崩溃。 这是一个更通用的Go文档规则的实例:除
问题内容: 我有以下代码实现了工作队列: 使用包含if语句(或内部没有任何内容)的for循环运行此代码,爬虫不会打印收到的消息。使用net / http中的ListenAndServe函数进行阻止,它将打印收到的消息。使用睡眠阻止1毫秒,我收到了消息。并将select语句放入for循环中,我也收到消息。 为什么没有select语句的for循环不允许执行在工作队列中发送的消息,以及我将如何处理这一问
问题内容: 我已经搜索过,但我只能找到有关另一种方式的问题:将stdin写入文件:) 有没有一种快速简便的方法将文件内容转储到stdout? 问题答案: 当然。假设您有一个字符串,文件名为,下面的技巧就可以了。
问题内容: 我有下一个代码: par.go 我用next运行它: 然后,确认此过程中有多少个线程: 您可以看到有5个线程。 如果我更改in代码的值,那么接下来的情况是: 我知道,去调度的后续机型,在这里,所以,是有(内核线程)。如果任何goroutine处于任何阻塞状态,则它们将从current脱离,并找到一个空闲的或新的if(如果找不到)。 所以,我的问题是:真的在阻止goroutine吗?如果
本文向大家介绍css加载会阻塞js运行吗?相关面试题,主要包含被问及css加载会阻塞js运行吗?时的应答技巧和注意事项,需要的朋友参考一下 参考文章
下面的代码是否阻止调用,如果是,如何使其成为非阻塞?i、 e.使反应式Java流的使用变得无用?如何在不阻塞呼叫的情况下分页? 目前,我有一个webClient调用后端服务,该服务返回