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

goroutines执行顺序

荆运诚
2023-03-14
问题内容

我试图理解这段代码,不确定为什么第二遍在第一遍之前执行。如果有人真的可以帮助我,那就太好了!

func sum(a []int, c chan int) {
   fmt.Println("summing: ", a)
   total := 0
   for _, v := range a {
      total += v
   }
   //fmt.Println("send to c",total)
   c <- total  // send total to c
}
func main() {
    //a := []int{7, 2, 8,134,23,23,1,23,1234,143, -9, 4, 0, 1234}

    c := make(chan int)

    go sum([]int{1,2,3}, c)
    go sum([]int{4,5,6}, c)

    x := <-c
    fmt.Println(x)
    x = <-c
    fmt.Println(x)
}

输出:

summing:  [4 5 6]
15
summing:  [1 2 3]
6

问题答案:

您没有任何内容可以显式同步两个goroutine的顺序。如果运行足够的时间,您将看到调用以fmt.Println不同的顺序进行打印。当执行goroutine时,由于它们是并发操作,因此无法保证它们将何时执行和/或完成。您需要使用各种标准库程序包或通道本身来同步并发运行的goroutine的执行。

例如(通过利用渠道的封锁性,您可以执行以下操作):

func main() {

    c := make(chan int)

    go sum([]int{1, 2, 3}, c)

    //use the channel to block until it receives a send
    x := <-c
    fmt.Println(x)

    //then execute the next routine
    go sum([]int{4, 5, 6}, c)

    x = <-c
    fmt.Println(x)
}

另一个示例(显然不那么实用,但是在这里查看其他常见的go同步功能),您可以引入一个等待组和一个通道范围:

func sum(a []int, c chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Println("summing: ", a)
    total := 0
    for _, v := range a {
        total += v
    }
    //fmt.Println("send to c",total)
    c <- total // send total to c
}

func main() {

    c := make(chan int)
    wg := new(sync.WaitGroup)

    //concurrently call the concurrent calls to sum, allowing execution to continue to the range of the channel 
    go func() {
        //increment the wait group, and pass it to the sum func to decrement it when it is complete
        wg.Add(1)
        go sum([]int{1, 2, 3}, c, wg)
        //wait for the above call to sum to complete
        wg.Wait()
        //and repeat...
        wg.Add(1)
        go sum([]int{4, 5, 6}, c, wg)
        wg.Wait()
        //all calls are complete, close the channel to allow the program to exit cleanly 
        close(c)
    }()

    //range of the channel
    for theSum := range c {
        x := theSum
        fmt.Println(x)
    }

}


 类似资料:
  • 类D 主要方法是 Bean配置文件是 程序的输出为:

  • 我正在比较算法(前n个数之和)的顺序和并行性能(使用ForkJoinPool): 我试着用不同的NumLoop来获得不同的值,但顺序法总是表现得更好,而且也是按3-4的顺序。 考虑到阵列大小并不是那么小,并行版本在这里的性能不应该更好吗。

  • 我无法确定spring security在何时何地执行身份验证管理器。我的意思是,certian过滤器按如下顺序执行: 但是当身份验证提供者对提供的用户名和密码进行身份验证时,我的意思是问下面这些过滤器是身份验证提供者执行的。 问候贾延德拉

  • 问题内容: 我们有一个基于石英的调度程序应用程序,该应用程序每分钟运行约1000个作业,每分钟的秒数均匀分布,即每秒约16-17个作业。理想情况下,这16-17个作业应同时触发,但是该作业的execute方法的第一个语句(仅记录执行时间)非常晚。例如,假设我们从05:00到05:04每分钟安排1000个作业。因此,理想情况下,计划在05:03:50进行的作业应该在05:03:50记录了execut

  • 我试图理解java中完整期货的非阻塞回调性质 有了上面的代码,我总是看到下面看到的输出 线程名称ForkJoinPool.common池工人-1 thenApply Thread name main thenApply Thread name main thenAcceptThread name main Thread name main 这个顺序似乎建议主线程等待所有Futures线程的执行。

  • 问题内容: 我正在学习Go,并且遇到了以下代码片段: 有人可以告诉我为什么“ sum”函数的第二个调用在第一个调用之前通过通道吗?在我看来,输出应为: 我还使用无缓冲通道对此进行了测试,它也给出了相同顺序的输出。我想念什么? 问题答案: 您正在代码中调用go例程,但无法确定例程何时结束并将该值传递到缓冲通道。 由于该代码是异步的,因此只要例程完成,它将把数据写入通道,并在另一侧读取。在上面的示例中