Skip to main content

Concurrency

In the previous chapter we started two goroutines in concurrent mode. Let's go back to our example and try to understand what concurrency actually means:

package main

import (
"fmt"
"time"
)

func main() {
start := time.Now()

go worker("Pam")
go worker("Jim")

time.Sleep(3 * time.Second) // let's wait for Pam and Jim

fmt.Printf("\nall work was done in %s seconds", time.Since(start))
}

func worker(name string) {
fmt.Printf("%s: doing my work...\n", name)
time.Sleep(2 * time.Second)
fmt.Printf("%s: done\n", name)
}

See it in playground

If you run this program several times, you will notice that the output is not always the same:

Jim: doing my work...
Pam: doing my work...
Pam: done
Jim: done
Pam: doing my work...
Jim: doing my work...
Jim: done
Pam: done

Why is this happening? It's because worker("Pam") and worker("Jim") run in concurrent mode.

So what is concurrency?

Concurrency means undefined out-of-order execution. This means goroutines run roughly in the same timeslot, but you don't really know which goroutine will start or finish first.

This is very different from parallelism. Parallelism happens when two or more concurrent functions run at the same time and is limited by your hardware: when you have at least 2 cores or hardware threads available. If you have only one processor only one function is running at a single point in time.

Rob Pike explained it better in his talk:

"But when people hear the word concurrency they often think of parallelism, a related but quite distinct concept. In programming, concurrency is the composition of independently executing processes, while parallelism is the simultaneous execution of (possibly related) computations. Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once."

[Concurrency is not parallelism]

I invite you to watch that talk and I hope by the end of it you will understand that concurrency is about the ability to run your program in independent pieces while parallelism is just a quality of that concurrency, quality given to you only with the help of hardware.

Coordinating goroutines

Now when you want to run concurrent functions, you don't usually want undefined behaviour like above. Having multiple functions running concurrently puts you in the place of coordinating those pieces. You need to orchestrate and synchronize your goroutines.

We saw a first problem solved by synchronization when we added a time.Sleep(3 * time.Second) because we needed main to wait for goroutines to finish. In other words, we synchronized main with the rest of other goroutines.

There is a better way to solve this than time.Sleep, and we will learn about it in the next chapter.

Notes

  • Concurrency means out of order execution.
  • Concurrency is not parallelism. Parallelism is about running things at the same time.
  • When dealing with concurrent functions you need to orchestrate and synchronize them to avoid undefined behaviour.