Golang模式一次杀死多个Goroutine

Golang模式一次杀死多个Goroutine,go,channel,goroutine,Go,Channel,Goroutine,我有两个goroutine,如下面的代码片段所示。我想同步它们,这样当一个返回时,另一个也应该退出。实现这一目标的最佳方式是什么 func main{ 围棋{ ... 如果错误!=零{ 回来 } } 围棋{ ... 如果错误!=零{ 回来 } } } 我在这里模拟了这个场景,并试图用一个通道来解决这个问题,以表明例程已经完成。这看起来像是对封闭通道的写入导致了死机。解决此问题的最佳方法是什么?您可以使用上下文在两个go例程之间进行通信。 比如说, 包干管 进口 上下文 同步 func main{

我有两个goroutine,如下面的代码片段所示。我想同步它们,这样当一个返回时,另一个也应该退出。实现这一目标的最佳方式是什么

func main{ 围棋{ ... 如果错误!=零{ 回来 } } 围棋{ ... 如果错误!=零{ 回来 } } }
我在这里模拟了这个场景,并试图用一个通道来解决这个问题,以表明例程已经完成。这看起来像是对封闭通道的写入导致了死机。解决此问题的最佳方法是什么?

您可以使用上下文在两个go例程之间进行通信。 比如说,

包干管 进口 上下文 同步 func main{ ctx,cancel:=context.WithCancelcontext.Background wg:=sync.WaitGroup{} 工作组增补3 围棋{ 延迟工作组完成 为了{ 挑选{ //来自其他goroutine饰面的味精
case您可以使用上下文在两个go例程之间进行通信。 比如说,

包干管 进口 上下文 同步 func main{ ctx,cancel:=context.WithCancelcontext.Background wg:=sync.WaitGroup{} 工作组增补3 围棋{ 延迟工作组完成 为了{ 挑选{ //来自其他goroutine饰面的味精 箱包总管 进口 fmt 同步 时间 func func1done chan结构{},wg*sync.WaitGroup{ 延迟工作组完成 timer1:=time.NewTicker1*时间。秒 timer2:=time.NewTicker2*time.Second 为了{ 挑选{ 箱包总管 进口 fmt 同步 时间 func func1done chan结构{},wg*sync.WaitGroup{ 延迟工作组完成 timer1:=time.NewTicker1*时间。秒 timer2:=time.NewTicker2*time.Second 为了{ 挑选{
案例< P>你的问题是,你希望在多个侦听器上接收到一个完成的通道上的一个发送。你还需要考虑一个发送的通道是否被你的GORATONE接收,或者你的主要功能。 我建议你将等待和完成频道分开

导入`同步` //此代码将等待两个函数完成后再结束 func main{ var wait sync.WaitGroup 等等 围棋{ 等等,完成了 } 去g{ 等等,完成了 } 等等,等等 } 现在,如何管理Done.Cond,解决方案是使用sync.Cond并让每个goroutine运行自己的goroutine来等待Cond。下面是一个示例:

包干管 进口 `fmt` `同步` `时间` //WaitForIt为一个更简单的API包装了一个Cond和一个Mutex: //.WAIT chan struct{}将返回一个 //等待完成时发出信号。 //.Done将指示WaitForIt已完成。 类型WaitForIt结构{ L*sync.Mutex Cond*sync.Cond } func NewWaitForIt*WaitForIt{ l:=&sync.Mutex{} c:=sync.NewCondl return&WaitForIt{l,c} } //WAIT返回一个chan,当 //Cond被触发。 func w*WaitForIt WAIT chan结构{}{ D:=makechan结构{} 围棋{ w、 L.锁 延迟w.L.解锁 w、 康德,等等
D> P>您的问题是,您希望在多个侦听器上接收完成的通道上的一个发送。您还需要考虑发送通道上的发送是否被GORATONE接收,或者由您的主要FUNC.< /P>接收。 我建议你将等待和完成频道分开

导入`同步` //此代码将等待两个函数完成后再结束 func main{ var wait sync.WaitGroup 等等 围棋{ 等等,完成了 } 去g{ 等等,完成了 } 等等,等等 } 现在,如何管理Done.Cond,解决方案是使用sync.Cond并让每个goroutine运行自己的goroutine来等待Cond。下面是一个示例:

包干管 进口 `fmt` `同步` `时间` //WaitForIt为一个更简单的API包装了一个Cond和一个Mutex: //.WAIT chan struct{}将返回一个 //等待完成时发出信号。 //.Done将指示WaitForIt已完成。 类型WaitForIt结构{ L*sync.Mutex Cond*sync.Cond } func NewWaitForIt*WaitForIt{ l:=&sync.Mutex{} c:=sync.NewCondl return&WaitForIt{l,c} } //WAIT返回一个chan,当 //Cond被触发。 func w*WaitForIt WAIT chan结构{}{ D:=makechan结构{} 围棋{ w、 L.锁 延迟w.L.解锁 w、 康德,等等
D在通道上使用close来发出完成信号。这允许多个goroutine通过在通道上接收来检查完成情况

每个goroutine使用一个通道来表示goroutine完成

done1 := make(chan struct{}) // closed when goroutine 1 returns
done2 := make(chan struct{}) // closed when goroutine 2 returns

go func() {
    defer close(done1)

    timer1 := time.NewTicker(1 * time.Second)
    defer timer1.Stop()

    timer2 := time.NewTicker(2 * time.Second)
    defer timer2.Stop()

    for {
        select {
        case <-done2:
            // The other goroutine returned.
            fmt.Println("done func 1")
            return
        case <-timer1.C:
            fmt.Println("timer1 func 1")
        case <-timer2.C:
            fmt.Println("timer2 func 1")
            return
        }

    }
}()

go func() {
    defer close(done2)
    for {
        select {
        case <-done1:
            // The other goroutine returned.
            fmt.Println("done func 2")
            return
        default:
            time.Sleep(3 * time.Second)
            fmt.Println("sleep done from func 2")
            return
        }

    }
}()

fmt.Println("waiting for goroutines to complete")

// Wait for both goroutines to return. The order that
// we wait here does not matter. 
<-done1
<-done2

fmt.Println("all done")

.

在通道上使用“关闭”来发出完成信号。这允许多个goroutine通过在通道上接收来检查完成情况

每个goroutine使用一个通道来表示goroutine完成

done1 := make(chan struct{}) // closed when goroutine 1 returns
done2 := make(chan struct{}) // closed when goroutine 2 returns

go func() {
    defer close(done1)

    timer1 := time.NewTicker(1 * time.Second)
    defer timer1.Stop()

    timer2 := time.NewTicker(2 * time.Second)
    defer timer2.Stop()

    for {
        select {
        case <-done2:
            // The other goroutine returned.
            fmt.Println("done func 1")
            return
        case <-timer1.C:
            fmt.Println("timer1 func 1")
        case <-timer2.C:
            fmt.Println("timer2 func 1")
            return
        }

    }
}()

go func() {
    defer close(done2)
    for {
        select {
        case <-done1:
            // The other goroutine returned.
            fmt.Println("done func 2")
            return
        default:
            time.Sleep(3 * time.Second)
            fmt.Println("sleep done from func 2")
            return
        }

    }
}()

fmt.Println("waiting for goroutines to complete")

// Wait for both goroutines to return. The order that
// we wait here does not matter. 
<-done1
<-done2

fmt.Println("all done")

>.

首先分离等待进行例行程序和完成频道

使用sync.WaitGroup来协调goroutines

func main{ 等待:=&sync.WaitGroup{} N:=3 等等
对于i:=1;i首先分离等待执行例程和完成通道

使用sync.WaitGroup来协调goroutines

func main{ 等待:=&sync.WaitGroup{} N:=3 等等

对于i:=1;我使用两个通道,使用接近信号完成交叉延迟关闭模式!?非常有意义。我认为我错误地认为这可以用一个通道解决。@CeriseLimón不会在这里处理完成的顺序问题吗?如果done2首先返回怎么办?将通道更改为缓冲大小为1可能是一个解决方案完成顺序无关紧要。主功能在打印消息并返回之前等待两个goroutine完成。使用两个通道,使用接近信号完成交叉延迟关闭模式!?很有意义。我认为我错误地认为这可以用一个通道解决。@CeriseLimón不支持do的顺序ne的问题在这里?如果done2先返回怎么办?更改要缓冲的通道大小为1可能是一个解决方案。完成顺序无关紧要。主函数在打印消息并返回之前等待两个Goroutine完成。谢谢!我需要阅读更多上下文。多次调用cancel是否会导致panic?不,不会。如果你觉得有帮助,你可以投票支持这个答案。thx~你的答案非常有帮助,我投了更高的票。但是在这种情况下使用上下文似乎是一种反模式,这就是为什么我不把它标为答案。@johne:你似乎误解了那篇博文。而Dave可能希望上下文和取消它不可否认,上下文是当前在Go中处理取消的方式。事实上,std库几乎完全使用上下文进行取消。只需看看net包中的用法,例如,以及os/exec、net/http等。更具体地说,http.Request中的取消通道状态:不推荐:改为使用NewRequestWithContext设置请求的上下文。谢谢!我需要阅读更多有关上下文的信息。多次调用取消是否会引起恐慌?不,不会。如果您觉得有帮助,可以对此答案投赞成票。thx~您的答案非常有帮助,我对其投了赞成票。但是在这种情况下使用上下文会导致恐慌吗我喜欢反模式,这就是为什么我不把它作为答案。@johne:你似乎误解了那篇博文。虽然Dave可能希望上下文和取消在将来以某种方式分开,但不可否认的是,上下文是当前在Go中处理取消的方式。事实上,std库几乎完全使用用于取消的上下文。只需查看网络包中的用法,例如,以及os/exec、net/http等。更具体地说,http中的Cancel通道。请求状态:已弃用:使用NewRequestWithContext设置请求的上下文。您准确地阐述了我的问题,比我做的好得多。在您和Cerise评论,我对如何解决这个问题有一个好主意。我是不是遗漏了什么?忽略这两个goroutine正在完成的等待。或者在这种情况下使用sync.Cond是必要的吗?我测试了一点,然后在关闭的频道上遇到了发送。我需要阅读sync.Cond,它让我头晕目眩,试图了解发生了什么继续,但这看起来是正确的答案。您不应该使用WaitForIt类.sync.Cond运行到封闭通道中,这确实有点棘手,但这正是您在这些情况下想要的:它是一个条件,可以让许多goroutine在一个条件下等待。等待通道的内容只是转换condit我把我的问题转化为一个chan,这样你就可以在一个选择中访问它。我会看看我是否可以使用WaitForIt和你的代码创建一个play示例。你精确地阐述了我的问题,比我做得好得多。在你和Cerise的评论之间,我对如何解决这个问题有一个好主意。我是否遗漏了什么?忽略这两个Goroutine的等待正在完成。或者在这种情况下使用sync.Cond是必要的吗?我做了更多的测试,在关闭的频道上遇到了send。我需要阅读sync.Cond,它让我头晕目眩,试图理解发生了什么,但这看起来是正确的答案。你不应该使用WaitForIt类运行到关闭的频道。sync.Cond确实有点棘手,但这正是您在这些情况下想要的:它是一个条件,可以让许多goroutine在一个条件下等待。等待频道的内容只是将条件转换为chan,以便您可以在select中访问它。我将看看是否可以使用WaitForIt创建一个播放示例密码