死锁问题+使用通道时goroutine数量增加
我正在使用Go开发一个简单的http状态检查程序。这个项目一开始进展顺利。然后我将频道引入其中,它不会停止。换句话说,不会触发WorkGroup.Done 如何触发工作组。完成 //前往游乐场:https://play.golang.org/p/1AzXEAV9p4K 包干管 进口 fmt net/http 运行时 同步 类型urlState结构{ url字符串 州议会 } func checklink string,c chan程序会为v:=范围c而阻塞,因为通道上的范围会一直持续到通道关闭。通过接收预期数量的值进行修复。此更改不需要WaitGroup死锁问题+使用通道时goroutine数量增加,go,Go,我正在使用Go开发一个简单的http状态检查程序。这个项目一开始进展顺利。然后我将频道引入其中,它不会停止。换句话说,不会触发WorkGroup.Done 如何触发工作组。完成 //前往游乐场:https://play.golang.org/p/1AzXEAV9p4K 包干管 进口 fmt net/http 运行时 同步 类型urlState结构{ url字符串 州议会 } func checklink string,c chan程序会为v:=范围c而阻塞,因为通道上的范围会一直持续到通道关闭。
result := true
stats := make(map[string]bool)
fmt.Println(`total sites: `, len(links))
c := make(chan urlState, len(links))
for _, link := range links {
stats[link] = false
fmt.Println(`requesting...`, link)
go checkLink(link, c)
fmt.Println(`goroutines: `, runtime.NumGoroutine())
}
for i := 0; i < len(links); i++ {
v := <-c
fmt.Println(`recv from channel, assigning result for `, v.url)
stats[v.url] = v.state
fmt.Println(`goroutines: `, runtime.NumGoroutine())
}
fmt.Println(`work finished!`)
for key, value := range stats {
fmt.Println(key, `---`, value)
if value == false {
result = false
}
}
你正在处理多少个链接?我不认为有任何理由它永远不会完成,但你已经有效地告诉它同时处理所有链接。如果有足够多的链接,这将是一个有效的分叉炸弹,而且您在启动goroutines时会消耗大量内存,因此它可能永远不会完成。如果有足够的内存和时间,它应该在逻辑上完成。您可能需要的是一次限制10、50或100个链接。@Flimzy这是一个有效点。当我使用不同的编程语言开发网络爬虫时,我遇到过类似的情况。然而,我写这段代码是为了适应围棋。即使只有一个链接,代码仍然没有完成。goplayder:
func checkLink(link string, c chan<- urlState, wg *sync.WaitGroup) {
defer wg.Done()
... remainder of function is same as before
}
func Check(links []string) bool {
result := true
stats := make(map[string]bool)
var wg sync.WaitGroup
fmt.Println(`total sites: `, len(links))
wg.Add(len(links)) // add workgroups of exactly same amount as links array length
c := make(chan urlState, len(links))
for _, link := range links {
stats[link] = false
fmt.Println(`requesting...`, link)
go checkLink(link, c, &wg)
fmt.Println(`goroutines: `, runtime.NumGoroutine())
}
// Close c when checkLink goroutines complete.
go func() {
wg.Wait()
close(c)
}()
for v := range c {
fmt.Println(`recv from channel, assigning result for `, v.url)
stats[v.url] = v.state
wg.Done()
fmt.Println(`goroutines: `, runtime.NumGoroutine())
}
fmt.Println(`work finished!`)
for key, value := range stats {
fmt.Println(key, `---`, value)
if value == false {
result = false
}
}
return result
}