S
S
S Pankov2020-04-24 19:22:13
go
S Pankov, 2020-04-24 19:22:13

How to do simple multithreading in golang?

There is a simple task. Run go application in N threads. The data for the threads is there before the threads are started and is added at runtime.

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup

    ok := make(chan int, 3)
    for i := 0; i < 2; i++ {
        wg.Add(1)

        go func(i int, wg *sync.WaitGroup) {
            for x := range ok {
                fmt.Println(i, x)
                if x >= 5 {
                    ok <- x - 1
                }
            }
            wg.Done()
        }(i, &wg)
    }

    ok <- 1
    ok <- 3
    ok <- 2
    ok <- 5
    ok <- 3
    ok <- 9

    wg.Wait()
}


I don't understand how to correctly "throw" into the channel so that everything does not fall at the end with a fatal error: all goroutines are asleep - deadlock!
To prevent this code from falling, you need to close the channel and do not add it there anymore. But I need more tasks to complete. How to organize it correctly?!

Answer the question

In order to leave comments, you need to log in

3 answer(s)
V
Vladislav, 2020-04-24
@ghostiam

You are blocking the main thread and the only goroutine, hence the deadlock.
Add a goroutine with an infinite loop and a slip to the very beginning and it will stop falling.
UPD
I would advise you to use a ready-made solution that I myself use github.com/xeoncross/goworkqueue , or just peep how it's done.

D
Dimonchik, 2020-04-24
@dimonchik2013

hehe
why close the channel?

D
di, 2020-04-26
@Delgus

I understand this - to stop the execution of the script, you need to understand that all the workers have finished working. Actually, go itself does this when it throws a panic fatal error: all goroutines are asleep - deadlock! Unfortunately, this panic occurs at runtime and it is impossible to catch it. The only way out by ourselves with a certain periodicity is to check whether our workers are working or working. The simplest solution is to add a counter of running goroutines and check it and the channel with tasks that it is also empty.
https://play.golang.org/p/K3grU-mmkRb

package main

import (
  "fmt"
  "time"
)

func main() {
  // задачи
  tasks := make(chan int, 2)
  // канал для расчета количества работающих воркеров
  working := make(chan int)
  // канал для остановки скрипта
  done := make(chan struct{})

  for i := 0; i < 2; i++ {
    go func(i int) {
      for x := range tasks {
        working <- 1
        fmt.Println(i, x)
        if x >= 5 {
          tasks <- x - 1
        }
        working <- -1
      }
    }(i)
  }

  // счетчик работающих горутин
  go func() {
    ticker := time.NewTicker(time.Second)
    // количество работающих воркеров
    var count int

    for {
      select {
      case w := <-working:
        count += w
      case <-ticker.C:
        if count == 0 && len(tasks) == 0 {
          close(done)
        }
      }
    }
  }()

  tasks <- 1
  tasks <- 3
  tasks <- 2
  tasks <- 5
  tasks <- 3
  tasks <- 9

  <-done
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question