Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I use concurrency in Go?

Tags:

So besides handling multiple server requests is there any other time that concurrency is relevant? I ask because it's so built into the language that I feel wasteful if I don't use it but I can barely find a use for it.

like image 288
ChasingLogic Avatar asked Nov 02 '13 23:11

ChasingLogic


People also ask

When should you use concurrency?

Another good use for concurrency is interacting with multiple input/output sources (disks, network, terminal, etc.). Your program should be able to wake up and do some work whenever a result comes from any of these sources. It is possible to do this with one thread and a system call like poll(2) or select(2).

Is Go good at concurrency?

The most robust programming language in terms of concurrency That's reason enough to talk about Go and its clever way of dealing with concurrency. Go is known for its first-class support for concurrency, or the ability for a program to deal with multiple things at once.

What is the use of concurrency in Golang?

In Go, concurrency works through the use of in-built functions known as Goroutines. Goroutines are functions, unique to Go, that run at the same time alongside other code or programs. They're not OS threads, though, they may be considered lightweight threads. Goroutines are deeply integrated with Go's runtime.

Is Go good for multithreading?

With Go, it's possible to do multi-threaded concurrency and parallelization with goroutines and goroutines work in an asynchronous way hence making use of both multi-threading and asynchronous programming efficiently.


2 Answers

Not an expert in Go (yet) but I'd say:

Whenever it is easiest to do so.

The beauty of the concurrency model in Go is that it is not fundamentally a multi-core architecture with checks and balances where things usually break - it is a multi-threaded paradigm that not only fits well into a multi-core architecture, it also fits well into a distributed system architecture.

You do not have to make special arrangements for multiple goroutines to work together harmoniously - they just do!

Here's an example of a naturally concurrent algorithm - I want to merge multiple channels into one. Once all of the input channels are exhausted I want to close the output channel.

It is just simpler to use concurrency - in fact it doesn't even look like concurrency - it looks almost procedural.

/*   Multiplex a number of channels into one. */ func Mux(channels []chan big.Int) chan big.Int {     // Count down as each channel closes. When hits zero - close ch.     var wg sync.WaitGroup     wg.Add(len(channels))     // The channel to output to.     ch := make(chan big.Int, len(channels))      // Make one go per channel.     for _, c := range channels {         go func(c <-chan big.Int) {             // Pump it.             for x := range c {                 ch <- x             }             // It closed.             wg.Done()         }(c)     }     // Close the channel when the pumping is finished.     go func() {         // Wait for everyone to be done.         wg.Wait()         // Close.         close(ch)     }()     return ch } 

The only concession I have to make to concurrency here is to use a sync.WaitGroup as a counter for concurrent counting.

Note that this is not purely my own work - I had a great deal of help with this here.

like image 60
OldCurmudgeon Avatar answered Oct 13 '22 07:10

OldCurmudgeon


Here is a good example from one of Go's inventors, Rob Pike, of using concurrency because it is an easier way to express the solution to a problem:

Lexical Scanning in Go

Generalizing on that a bit, any producer-consumer problem is a natural fit for 2 goroutines using a channel to pass outputs from the producer to the consumer.

Another good use for concurrency is interacting with multiple input/output sources (disks, network, terminal, etc.). Your program should be able to wake up and do some work whenever a result comes from any of these sources. It is possible to do this with one thread and a system call like poll(2) or select(2). When your thread wakes up, it must figure out which result came in, find where it left off in the relevant task, and pick up from there. That's a lot of code you need to write.

Writing that code is much easier using one goroutine per task. Then the state of that task is captured implicitly in the goroutine, and picking up where it left off is as simple as waking up and running.

like image 43
Sean Avatar answered Oct 13 '22 07:10

Sean