Answer the question
In order to leave comments, you need to log in
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:
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
}
Answer the question
In order to leave comments, you need to log in
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...
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 questionAsk a Question
731 491 924 answers to any question