Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Always have x number of goroutines running at any time

Tags:

go

goroutine

I see lots of tutorials and examples on how to make Go wait for x number of goroutines to finish, but what I'm trying to do is have ensure there are always x number running, so a new goroutine is launched as soon as one ends.

Specifically I have a few hundred thousand 'things to do' which is processing some stuff that is coming out of MySQL. So it works like this:

db, err := sql.Open("mysql", connection_string) checkErr(err) defer db.Close()  rows,err := db.Query(`SELECT id FROM table`) checkErr(err) defer rows.Close()  var id uint for rows.Next() {     err := rows.Scan(&id)     checkErr(err)     go processTheThing(id)     } checkErr(err) rows.Close() 

Currently that will launch several hundred thousand threads of processTheThing(). What I need is that a maximum of x number (we'll call it 20) goroutines are launched. So it starts by launching 20 for the first 20 rows, and from then on it will launch a new goroutine for the next id the moment that one of the current goroutines has finished. So at any point in time there are always 20 running.

I'm sure this is quite simple/standard, but I can't seem to find a good explanation on any of the tutorials or examples or how this is done.

like image 406
Alasdair Avatar asked Aug 14 '14 10:08

Alasdair


People also ask

How many Goroutines can I run?

In the case of goroutines, since stack size can grow dynamically, you can spawn 1000 goroutines without a problem. As a goroutine starts with 8KB (2KB since Go 1.4) of stack space, most of them generally don't grow bigger than that.

When should we use Goroutines?

Goroutines are useful when you want to do multiple things simultaneously. For example, if you have ten things you want to do at the same time, you can do each one on a separate goroutine, and wait for all of them to finish.

How do you control Goroutines?

You can't kill a goroutine from outside. You can signal a goroutine to stop using a channel, but there's no handle on goroutines to do any sort of meta management. Goroutines are intended to cooperatively solve problems, so killing one that is misbehaving would almost never be an adequate response.

How do Goroutines run?

To run a function as a goroutine (as opposed to a standard synchronous function), you only need to add the go keyword before the function call. However, for the program to run the goroutines concurrently, you'll need to make one additional change.


1 Answers

You may find Go Concurrency Patterns article interesting, especially Bounded parallelism section, it explains the exact pattern you need.

You can use channel of empty structs as a limiting guard to control number of concurrent worker goroutines:

package main  import "fmt"  func main() {     maxGoroutines := 10     guard := make(chan struct{}, maxGoroutines)      for i := 0; i < 30; i++ {         guard <- struct{}{} // would block if guard channel is already filled         go func(n int) {             worker(n)             <-guard         }(i)     } }  func worker(i int) { fmt.Println("doing work on", i) } 
like image 186
artyom Avatar answered Sep 21 '22 14:09

artyom