首页 >后端开发 >Golang >为什么带 Goroutine 的 Go Select 语句会挂起,除非添加 Print 语句?

为什么带 Goroutine 的 Go Select 语句会挂起,除非添加 Print 语句?

Linda Hamilton
Linda Hamilton原创
2024-11-26 22:46:11445浏览

Why Does a Go Select Statement with a Goroutine Hang Unless a Print Statement is Added?

带有 Select 的 Goroutine 不会停止,除非添加打印语句

在 Go Tour 练习 #71 中,使用不带默认值的 select语句可能会导致无限循环,从而阻止 goroutine 退出。使用 nogood 参数运行 71_hang.go 时会遇到此问题,但使用 ok 参数则不会。

两种场景之间的区别在于默认情况下存在额外的 fmt.Print("") 语句select 语句的情况。默认情况下,选择块直到其中一个通道有消息要接收。然而,在默认情况下,即使没有通道有消息可用,select 也会执行默认语句。

在原始代码中,没有 fmt.Print("") 语句,select 语句输入了一个无限循环,因为没有可用消息的通道,并且默认情况下不执行任何操作来允许 goroutine 进行调度。添加 fmt.Print("") 语句允许调度程序调度其他 goroutine 并打破无限循环。

或者,可以修改代码以非阻塞方式使用 select,从而允许其他 goroutine才能正常运行。这可以通过删除默认语句并使用单独的 if 语句来检查抓取计数器是否已达到零来实现,如下面修改后的代码所示:

for {
    select {
        case todo := <-toDoList:
            if todo.depth > 0 && !visited[todo.url] {
                crawling++
                visited[todo.url] = true
                go crawl(todo, fetcher, toDoList, doneCrawling)
            }
        case <-doneCrawling:
            crawling--
    }
    if crawling == 0 {
        break
    }
}

以上是为什么带 Goroutine 的 Go Select 语句会挂起,除非添加 Print 语句?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn