去lang复用所有goroutines睡着了 - 僵局 [英] Go lang multiplexing all goroutines are asleep - deadlock

查看:141
本文介绍了去lang复用所有goroutines睡着了 - 僵局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  package main $ 

使用多个go例程创建fan-in函数返回channel这里是我的代码。 b
$ b进口(
fmt
数学/兰特
同步
时间


var wg,wg2 sync.WaitGroup

func main(){
final:= talk(boring(Joe),boring(Ann))
for我:= 0;我< 10; i ++ {
fmt.Println(< -final)
}
fmt.Println(你们都很无聊,我要离开)
}

func talk(input1,input2< -chan string)< -chan string {
out:= make(chan string)
go func(){
wg.Add(1 )
用于{
出< - < -input1
}
}()
去func(){
wg.Add(1)
为{
out < - <-input2
}
}()
wg.Done()
关闭(出)
返回
}

func boring(msg string)< -chan string {
c:= make(chan string)
for i:= 0;我< 5; i ++ {
c< - fmt.Sprintf(%s%d \ n,msg,i)
time.Sleep(time.Duration(rand.Intn(1e3))* time.Millisecond )
}
return c
}

但我得到运行以上代码后出错


所有goroutines都睡着了 - 死锁


我试图关闭频道,但仍然给了我错误。我曾尝试将无聊的返回频道分配给Joe和Ann,然后通过这些频道进行多路复用的功能通话,但仍然没有成功。我很新的去了解这个概念不清楚的渠道。

解决方案

您可以使用 select


select 语句允许一个goroutine等待多次通信
操作。



选择直到其中一个案例可以运行,然后执行该
案例。



  package main 
$ b它随机选择一个。 b










$ b :=说话(无聊(乔),无聊(安))
为我:= 0;我< 10; i ++ {
fmt.Println(< -final)
}
fmt.Println(你们都很无聊,我要离开)
}

func talk(input1,input2< -chan string)< -chan string {
c:= make(chan string)
func(){
for {
选择{
case s:=< -input1:
c< - s
case s:=< -input2:
c< - s
}
}
}()
return c
}

func boring(msg string)< -chan string {
c:= make chan字符串)
去func(){
for i:= 0;我< 5; i ++ {
c< - fmt.Sprintf(%s:%d,msg,i)
time.Sleep(time.Duration(rand.Intn(1e3))* time.Millisecond)

$(b


code

$ b $ p >
试玩Playground



编辑:



在给出的例子中, boring 函数不使用goroutine for重复发送频道将永远阻止,因为:
https://tour.golang.org / concurrency / 2


默认情况下,发送和接收阻塞,直到另一方准备好。
这允许goroutines在没有显式锁定或
条件变量的情况下进行同步。

另外, wg.Done()需要成为goroutine的一部分。



通过执行上述更改,我得到了它的工作: https://play.golang.org/p/YN0kfBO6iT


I wants to create a fan-in function using multiple go routines returning channel here is my code.

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

var wg, wg2 sync.WaitGroup

func main() {
    final := talk(boring("Joe"), boring("Ann"))
    for i := 0; i < 10; i++ {
        fmt.Println(<-final)
    }
    fmt.Println("You are both boring I'm leaving")
}

func talk(input1, input2 <-chan string) <-chan string {
    out := make(chan string)
    go func() {
        wg.Add(1)
        for {
            out <- <-input1
        }
    }()
    go func() {
        wg.Add(1)
        for {
            out <- <-input2
        }
    }()
    wg.Done()
    close(out)
    return out
}

func boring(msg string) <-chan string {
    c := make(chan string)
    for i := 0; i < 5; i++ {
        c <- fmt.Sprintf("%s%d\n", msg, i)
        time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
    }
    return c
}

But I got an error after running above code

all goroutines are asleep - deadlock

I have tried to close channels but still it is giving me the error. I have tried to assign boring returned channels to Joe and Ann and then pass those channels to talk function for multiplexing still no success. I am new to go learning channels not clear on this concept.

解决方案

Instead of wait groups, you can use select: https://tour.golang.org/concurrency/5

The select statement lets a goroutine wait on multiple communication operations.

A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    final := talk(boring("Joe"), boring("Ann"))
    for i := 0; i < 10; i++ {
        fmt.Println(<-final)
    }
    fmt.Println("You are both boring I'm leaving")
}

func talk(input1, input2 <-chan string) <-chan string {
    c := make(chan string)
    go func() {
        for {
            select {
            case s := <-input1:
                c <- s
            case s := <-input2:
                c <- s
            }
        }
    }()
    return c
}

func boring(msg string) <-chan string {
    c := make(chan string)
    go func() {
        for i := 0; i < 5; i++ {
            c <- fmt.Sprintf("%s: %d", msg, i)
            time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)
        }
    }()
    return c
}

Try it on Playground

Edit:

In your given example, boring function doesn't use goroutine for repeated send over channel which will block forever, because: https://tour.golang.org/concurrency/2

By default, sends and receives block until the other side is ready. This allows goroutines to synchronize without explicit locks or condition variables.

Also, wg.Done() needs to be part of goroutine.

I got it working by doing above changes: https://play.golang.org/p/YN0kfBO6iT

这篇关于去lang复用所有goroutines睡着了 - 僵局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆