未从戈鲁廷获得预期输出

我在(https://www.geeksforgeeks.org/channel-in-golang/)上读到:


“在信道中,发送和接收操作阻塞,直到另一端默认未就绪。它允许戈鲁廷在没有显式锁或条件变量的情况下相互同步。


为了测试上面的语句,我编写了一个示例程序,如下所述:


程序:


package main

import (

    "fmt"

    "sync"

    "time"

)


func myFunc(ch chan int) {

    fmt.Println("Inside goroutine:: myFunc()")

    fmt.Println(10 + <-ch) //<-- According to rule, control will be blocked here until 'ch' sends some data so that it will be received in our myFunc() go routine.

}

func main() {


    fmt.Println("Start Main method")

    // Creating a channel

    ch := make(chan int)


    go myFunc(ch) //<-- This go routine started in a new thread


    time.Sleep(2 * time.Second) //<--- introduced a Sleep of 2 seconds to ensure that myFunc() go routine executes before main thread

    ch <- 10

    fmt.Println("End Main method")

}

我期待下面的输出:


Start Main method


Inside goroutine:: myFunc()


20


End Main method

但是,实际接收的输出是:


Start Main method


Inside goroutine:: myFunc()


End Main method

为什么通过通道发送的值没有打印出来?我认为,这是因为主线程首先完成了它的执行,因此,所有其他goroutine也终止了。


如果是这样的话,那么,为什么规则说 - 它允许goroutine在没有显式锁或条件变量的情况下相互同步。


因为,为了获得预期的输出,我必须使用告诉主线程等待另一个 goroutine 完成。这不是违反了上述规则,因为我以等待组的形式使用锁?sync.WaitGroup


PS:我正在学习戈朗。所以,如果我完全理解了这个概念,请原谅。


慕标5832272
浏览 117回答 4
4回答

江户川乱折腾

试试这个,使用你的代码作为基础package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "time")func myFunc(ch chan int, done chan struct{}) {&nbsp; &nbsp; defer close(done) // channel will be closed in the function exit phase&nbsp; &nbsp; fmt.Println("Inside goroutine:: myFunc()")&nbsp; &nbsp; fmt.Println(10 + <-ch) //<-- According to rule, control will be blocked here until 'ch' sends some data so that it will be received in our myFunc() go routine.}func main() {&nbsp; &nbsp; fmt.Println("Start Main method")&nbsp; &nbsp; // Creating a channel&nbsp; &nbsp; ch := make(chan int)&nbsp; &nbsp; done := make(chan struct{}) // signal channel&nbsp; &nbsp; go myFunc(ch, done) //<-- This go routine started in a new thread&nbsp; &nbsp; time.Sleep(2 * time.Second) //<--- introduced a Sleep of 2 seconds to ensure that myFunc() go routine executes before main thread&nbsp; &nbsp; ch <- 10&nbsp; &nbsp; <-done // waiting for function complete&nbsp; &nbsp; fmt.Println("End Main method")}或者使用雅罗斯瓦夫的建议。

BIG阳

主戈鲁廷在戈鲁廷能够打印输出之前就已存在。下面是一个实现,它确保戈鲁廷在主戈鲁丁退出之前完成。myFuncmyFuncpackage mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "sync"&nbsp; &nbsp; "time")func myFunc(ch chan int, wg *sync.WaitGroup) {&nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; fmt.Println("Inside goroutine:: myFunc()")&nbsp; &nbsp; fmt.Println(10 + <-ch) //<-- According to rule, control will be blocked here until 'ch' sends some data so that it will be received in our myFunc() go routine.}func main() {&nbsp; &nbsp; fmt.Println("Start Main method")&nbsp; &nbsp; // Creating a channel&nbsp; &nbsp; ch := make(chan int)&nbsp; &nbsp; wg := sync.WaitGroup{}&nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; go myFunc(ch, &wg) //<-- This go routine started in a new thread&nbsp; &nbsp; time.Sleep(2 * time.Second) //<--- introduced a Sleep of 2 seconds to ensure that myFunc() go routine executes before main thread&nbsp; &nbsp; ch <- 10&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; fmt.Println("End Main method")}此处的通道用于同步,其工作方式与文档中的说明相同。这并不意味着从代码中的这一点开始的代码将以相同的速度执行。这只意味着如果戈鲁廷没有从频道读取,主戈鲁廷将不会继续。并将等待主戈鲁丁将数据推送到通道。发生这种情况后,两个哥律特将继续独立执行。myFuncmyFunc

蓝山帝景

因为去太快了...https://play.golang.org/p/LNyDAA3mGYY发送到频道调度程序后,速度不快...和程序存在。我为调度程序引入了一个额外的上下文切换器来显示效果。

长风秋雁

是的,你是对的我认为,这是因为主线程首先完成了它的执行,因此,所有其他goroutine也终止了。如果您检查上述程序的执行情况。休眠状态是在主线程写入通道之前。现在即使哪个 goroutine() 将有 CPU 时间是完全任意的,但在上述情况下,如果休眠在逻辑之前。 将被阻止,因为 中没有数据mainexplicit sleepmyFuncch在这里,我对上面的代码进行了轻微的更改,以便在将数据写入 Channel 后进行睡眠。它提供预期的输出,不使用 或 。mainwaitgroupquit channelspackage mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "time")func myFunc(ch chan int) {&nbsp; &nbsp; fmt.Println("Inside goroutine:: myFunc()")&nbsp; &nbsp; fmt.Println(10 + <-ch) //<-- According to rule, control will be blocked here until 'ch' sends some data so that it will be received in our myFunc() go routine.}func main() {&nbsp; &nbsp; fmt.Println("Start Main method")&nbsp; &nbsp; // Creating a channel&nbsp; &nbsp; ch := make(chan int)&nbsp; &nbsp; go myFunc(ch) //<-- This go routine started in a new thread&nbsp; &nbsp;&nbsp; &nbsp; ch <- 10&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; time.Sleep(2 * time.Second) //<--- introduced a Sleep of 2 seconds to ensure that myFunc() go routine executes before main thread&nbsp; &nbsp; fmt.Println("End Main method")}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go