当前位置: 首页 > 面试题库 >

如果有时间,Goroutine不会执行。包括睡眠

凌嘉志
2023-03-14
问题内容

以下代码运行良好:

package main

import (
    "fmt"
)

func my_func(c chan int){
    fmt.Println(<-c)
}

func main(){
    c := make(chan int)
    go my_func(c)

    c<-3
}

playgound_1

但是如果我改变

c<-3

time.Sleep(time.Second)
c<-3

游乐场_2

我的代码无法执行。

我的直觉是mainmy_func完成执行之前,某种方式会返回,但是似乎添加暂停应该没有任何效果。我对这个简单的例子完全迷失了,这是怎么回事?


问题答案:

main函数结束时,它的程序结束。它不等待其他goroutine完成。

引用Go语言规范:程序执行:

程序执行首先初始化主程序包,然后调用函数main。当该函数调用返回时,程序退出。它不等待其他(非main)goroutine完成。

因此,只要您的main功能通过在通道上发送值成功完成,该程序就可能立即终止,而另一个goroutine才有机会将接收到的值打印到控制台。

如果要确保将值打印到控制台,则必须将其与从main函数退出的事件进行同步:

具有“完成”频道的示例(在Go Playground上尝试):

func my_func(c, done chan int) {
    fmt.Println(<-c)
    done <- 1
}

func main() {
    c := make(chan int)
    done := make(chan int)
    go my_func(c, done)

    time.Sleep(time.Second)
    c <- 3
    <-done
}

由于done也是一个未缓冲的通道,因此在main函数结束时从该通道接收数据必须等待该done通道上的值发送,这c是在接收到通道上发送的值并将其打印到控制台后发生的。

对于看似不确定的运行的解释:

够程可能会或可能不会被并行执行 在同一时间 。同步可确保某些事件先于其他事件发生。那是您获得的唯一保证,也是您应该依靠的唯一东西。 发生以下
2个示例:

  • go启动新的goroutine 的语句发生在goroutine的执行开始之前。
  • 通道上的发送发生在该通道上的相应接收完成之前。

有关更多详细信息,请阅读 Go Memory Model

回到您的示例:

来自未缓冲通道的接收发生在该通道上的发送完成之前。

因此,您获得的唯一保证是,运行的goroutine
my_func()将从c发送的通道接收值main()。但是,一旦接收到该值,该main函数就 可以
继续执行,但是由于发送后没有更多的语句,因此它仅随程序一起结束。无论非main够程将有 时间机会 与打印fmt.Println()
没有定义



 类似资料:
  • 问题内容: 关于PHP中的函数,我有两个问题: 睡眠时间是否会影响我的PHP脚本的最大执行时间限制?有时,PHP显示消息“超过30秒的最大执行时间”。如果我使用此消息会出现吗? 使用该功能有没有风险?它会消耗很多CPU性能吗? 问题答案: 您应该尝试一下,只需让脚本hibernate超过您的最大执行时间即可。 Spoiler:在Linux下,睡眠时间被忽略,但是在Windows下,它计为执行时间。

  • 问题内容: 例如,有没有一种我可以执行的方法 然后在需要时“唤醒”睡眠的goroutine? 我看到里面有一个,但是我无法调用它。有什么想法吗? 问题答案: 没有办法中断,但是,您可以使用和语句来获取所需的功能。 一个简单的例子来展示基本思想: http://play.golang.org/p/7uKfItZbKG 在此示例中,我们生成了一个信令goroutine来告知main停止暂停。主要是在两

  • 我正在调用while循环内的线程Hibernate1秒。当标志为true时,循环将运行(标志为true无限时间)。在循环内,线程应Hibernate1秒,唤醒并增加计数器,检查IF条件,如果为FALSE,则应再次Hibernate1秒并继续29次。在第30次迭代中,IF条件为true,IF语句中调用的方法将收集并存储数据。最后,在第32次迭代中,第二个IF语句将把存储的数据发送到服务器,并将计数设

  • 我试图通过spring Boot2实现的api向prometheus公开定时度量。我包含了以下依赖项。 我通过spring-cloud-starter-parent finchley.sr1来管理依赖关系,它给了我关于spring-boot-starter-acturet的2.0.4.release版本和关于micrometer-registry-prometheus的1.0.6版本。 /actu

  • 问题内容: 对于我的要求之一,我必须创建N个工作程序例程,该例程将由一个监视程序监视。所有工作程序完成后,监视程序必须结束。我的代码以死锁结尾,请帮忙。 问题答案: 您的monitorWorker永不死。当所有工作人员完成时,它将继续等待cs。这将导致死锁,因为其他任何东西都不会继续发送给CS,因此wg永远不会达到0。一种可能的解决方法是,当所有工作程序完成时,让监视器关闭通道。如果for循环在m

  • 我正在尝试获得一些执行建议。当我使用不带参数的注释时,它会执行,但当注释包含参数时,它不会执行。 注释: 注释的使用: