All moves go to sleep - a dead end

I build the skeleton of the working system using Go, and I get a "fatal error: all the mountains were asleep - a dead end!".

I use two channels for coordination, one for creating tasks and one for sending results. After creating the tasks, I close the input channel.

My question is how to close the output channel so that the program can exit correctly. Code:

package main

import (
    "bufio"
    "flag"
    "fmt"
    "log"
    "math/rand"
    "os"
    "time"
)

type Work struct {
    id int
    ts time.Duration
}

const (
    NumWorkers = 5000
    NumJobs    = 100000
)

func worker(in <-chan *Work, out chan<- *Work) {
    for w := range in {
        st := time.Now()
        time.Sleep(time.Duration(rand.Int63n(int64(200 * time.Millisecond))))
        w.ts = time.Since(st)
        out <- w
    }
}

func main() {
    wait := flag.Bool("w", false, "wait for <enter> before starting")
    flag.Parse()

    if *wait {
        fmt.Printf("I'm <%d>, press <enter> to continue", os.Getpid())
        reader := bufio.NewReader(os.Stdin)
        reader.ReadString('\n')
    }

    Run()
}

func Run() {
    in, out := make(chan *Work, 100), make(chan *Work, 100)
    for i := 0; i < NumWorkers; i++ {
        go worker(in, out)
    }
    go createJobs(in)
    receiveResults(out)
}

func createJobs(queue chan<- *Work) {
    for i := 0; i < NumJobs; i++ {
        work := &Work{i, 0}
        queue <- work
    }
    close(queue)
}

func receiveResults(completed <-chan *Work) {
    for w := range completed {
        log.Printf("job %d completed in %s", w.id, w.ts)
    }
}

Any help is appreciated :)

+1
source share
1 answer

I skipped the part that you know the reason for the deadlock in the original answer.

  • You mentioned WaitGroup, it's basically just a semaphore
  • You can use another “control” channel on which workers work when they are running.

-

func worker(ctrl chan<- bool, in <-chan *Work, out chan<- *Work) {
    for w := range in {
        st := time.Now()
        time.Sleep(time.Duration(rand.Int63n(int64(200 * time.Millisecond))))
        w.ts = time.Since(st)
        out <- w
    }
    ctrl <- true
}

func control(ctrl <-chan bool, numWorkers int, out chan<- *Work) {
    for i=0; i<numWorkers; i++ {
        <-ctrl
    }
    close(out)
}

:

range:

for w := range completed {
    log.Printf("job %d completed in %s", w.id, w.ts)
}

+1

Source: https://habr.com/ru/post/1526972/


All Articles