duan89197 2019-09-12 00:44
浏览 37

为什么会有僵局?

I have tried to recreate a situation below, wherein I am trying to run three functions concurrently. However, I can only run the second and third function after a certain point in the first function, since it depends on a value from the first function. For this case, I used a channel. Here's my code:

package code
import "fmt"

func First(c chan string) {
    for i := 0; i < 10000; i++ {
        continue
    }
    test := "test"
    fmt.Println(test)
    c <- test
    for i := 0; i < 10000; i++ {
        fmt.Print(i)
    }
}

func Second(c chan string) {
    msg:= <- c
    fmt.Println(msg)
    if msg != "" {  // I need to run the whole of First before running second and third concurrently then
        fmt.Println("second", msg)
        for i := 0; i < 10000; i++ {
            fmt.Print(i)
        }
    }
}

func Third(c chan string) {
    msg:= <- c
    fmt.Println("third", msg)
    for i := 0; i < 10000; i++ {
        fmt.Print(i)
    }
}
package main

import (
    "./code"
    "fmt"
    "sync"

    //"sync"
    "time"
)
func main() {
    start := time.Now()
    var wg sync.WaitGroup
    wg.Add(3)
    var c chan string = make(chan string)
    go func() {
        code.First(c)
        wg.Done()
    }()
    go func() {
        code.Second(c)
        wg.Done()
    }()
    go func() {
        code.Third(c)
        wg.Done()
    }()
    wg.Wait()
    end := time.Now()
    delta := end.Sub(start)
    fmt.Println("time", delta.Seconds())
}

Currently, I am getting a deadlock. A couple extra questions- is there a way to first check the values given by the channel, and if they are not certain expected values I first complete running the first function and then run second and third concurrently? Essentially a check like the one I added in second? If it is the expected value I'd like all the functions to run concurrently after the channel gets particular values from the first function.

  • 写回答

1条回答 默认 最新

  • douzhi7661 2019-09-12 01:03
    关注

    Your main program spawns off three extra goroutines, and then waits for all three to signal (via wg.Done) that they are done. All three goroutines, plus main itself, share one channel over which you can send one string instance at a time (and which you use to send exactly one).

    One goroutine (which calls code.First) spins for a bit and then sends a string. Once the string is sent, that goroutine prints many numbers, then signals done-ness and quits.

    Two other goroutines (which call code.Second and code.Third) immediately block waiting to receive a string. Depending on precisely when they run and the vagaries of who gets the string, one of them will get the string that code.First sends. The other remains blocked.

    Whichever one gets a string (which is currently always "test"), that one then prints its name and many numbers, then signals done-ness and quits.

    Whichever one didn't get a string is still waiting for a string. Meanwhile, the wg.Wait in main is waiting for the last wg.Done call, which can no longer occur as all remaining goroutines are waiting (there are now just these two—main and whichever didn't get the string—left). This is your deadlock.

    It looks as though you expected both goroutines to receive the string that was sent from code.First. That does not happen: one of them gets the string, and the other continues waiting. (There is no promise as to who gets the string.)

    A couple extra questions- is there a way to first check the values given by the channel ...

    Sure: whatever string you get, you have a string. You can do whatever operation you like with it, just as you already compare it to "".

    ... and if they are not certain expected values I first complete running the first function and then run second and third concurrently

    That's just a Small Matter Of Programming. If you wish to be able to control who gets which message(s), though, you'll need one channel per receiving goroutine. If you make two separate channels, code.First can take both, and can send an appropriate message to either additional goroutine at whatever point you like.

    评论

报告相同问题?

悬赏问题

  • ¥15 想问一下stata17中这段代码哪里有问题呀
  • ¥15 flink cdc无法实时同步mysql数据
  • ¥100 有人会搭建GPT-J-6B框架吗?有偿
  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决