调整GOPL并发Web Crawler代码顺序后失效的原因咨询
为什么调整代码顺序后爬虫无法正常运行?
这个问题的核心在于Go语言中无缓冲通道的阻塞特性和代码执行的顺序逻辑,咱们一步步拆解:
先看原代码的正确逻辑
原代码里,我们先启动20个爬虫goroutine,这些goroutine会立刻开始监听unseenLinks通道,等待接收要爬取的链接。同时,main goroutine再初始化seen去重map,然后往worklist发送初始链接,接着进入循环处理worklist里的链接——这时候,发送到worklist的数据能被后续流程处理,unseenLinks的发送也有对应的goroutine接收,整个流程是通的。
调整顺序后出了什么问题?
当你把seen初始化和worklist的处理循环放到启动goroutine之前,代码的执行顺序变成了这样:
- 创建
worklist和unseenLinks两个无缓冲通道。 - 初始化
seenmap。 - 执行
worklist <- []string{"https://golang.org"}——这里直接卡死!
无缓冲通道的发送操作是阻塞式的:必须有一个接收方已经准备好接收数据,发送才能完成。但此时,main goroutine还没进入for list := range worklist的接收循环,也没有任何其他goroutine在监听worklist(因为启动爬虫goroutine的代码还没执行到)。所以这一步会让main goroutine永久阻塞,程序完全停在这里,后面的代码(包括启动爬虫goroutine)根本没机会运行。
就算我们假设worklist是带缓冲的(比如缓冲大小为1),让初始发送能成功,接下来main进入for list := range worklist循环处理链接,当它往unseenLinks发送链接时,同样会遇到问题:此时爬虫goroutine还没启动,没有接收方,unseenLinks <- link又会让main goroutine卡死,还是无法执行到启动goroutine的代码。
总结一下
调整顺序后,程序在执行到通道发送操作时,因为没有对应的接收方就绪,导致main goroutine提前阻塞,后续启动爬虫goroutine的代码无法执行,整个并发流程彻底断裂,自然无法正常运行。
内容的提问来源于stack exchange,提问作者Pauli
相关产品推荐
相关产品推荐

