V
V
Void Vasher2021-03-16 21:21:25
go
Void Vasher, 2021-03-16 21:21:25

The best way to avoid the race condition, in this case?

Hello.

There is a service that processes some data flow by a pool of workers.

Here is a simplified code for demonstration purposes:

spoiler
package main

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

var (
  maxWorkers = 5

  pool    = make(chan struct{}, maxWorkers)
  input   = make(chan int, 0)
  results = make([]int, 0)
)

func main() {
  go func() {
    defer close(input)

    // какой-то рандомный input
    rand.Seed(time.Now().Unix())
    limit := rand.Intn(40) + 1

    for i := 0; i < limit; i++ {
      input <- i
    }
  }()

  var wg sync.WaitGroup

  // главный процесс пула воркеров
  for i := range input {
    pool <- struct{}{}
    wg.Add(1)

    go func(i int) {
      defer func() {
        wg.Done()
        <-pool
      }()

      // здесь race condition
      results = append(results, pow(i+1, 2))
    }(i)
  }

  wg.Wait()

  fmt.Println(results)
}

func pow(n int, power int) int {
  fmt.Println("worker started")
  time.Sleep(time.Second * 2)

  return n * power
}


How to avoid the race condition in this case? Mutex will not help here, as it will block all workers, and they will be executed in turn.
Of the options: use an additional channel.
But maybe there is a more convenient way?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
V
Vladislav, 2021-03-17
@AlgollY

Channel examples
When we know the amount of data:
https://play.golang.org/p/7pNGCebvqlo
When we don't know:
https://play.golang.org/p/7WtVnXwjtuo
Details in the comments:
https://qna. habr.com/answer?answer_id=1901263#comm...

R
raiboon, 2021-03-16
@raiboon

Two options.
1. Mutex. What makes you think that the workers will be executed in turn? First, some long work is done competitively, and then the mutex closes the slice for a short period of time while the result is being added to it.
2. Channel. The point is that the results are collected in one goroutine. Then there will be no competitive write to the slice. It's more of a go way. This can be done in main or run another one.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question