appendix EConcurrent programming

 
Concurrency is dealing with a lot of things at once. Parallelism is doing a lot of things at once. —Rob Pike, from his Waza talk (https://go.dev/blog/waza-talk)

Concurrency may involve parallelism, but these two concepts are not the same. Concurrency is about structuring the code, whereas parallelism is about executing the code simultaneously.

Many goroutines can run concurrently on a single CPU through context switching, whereas parallelism may occur when multiple CPUs execute goroutines simultaneously. Grasping this distinction helps us structure concurrent code regardless of the number of available CPUs.

In this appendix, we’ll explore goroutines and channels. This appendix builds on concepts introduced in chapter 1; it’s a good idea to review that chapter to understand those concepts fully. Throughout the appendix, we may omit package and import declarations from listings to save space and trees. Listings can also omit the work function after we declare it in section E.1.1. In any case, assume that the package is main and the work function is declared.

E.1 Goroutines

Goroutines are lightweight, independently running concurrent functions. They can handle multiple tasks concurrently without the overhead of traditional threads. We’ll examine how to start a goroutine and see the differences between running sequential and concurrent code.

E.1.1 Running sequentially

E.1.2 Running concurrently

E.2 Using WaitGroup

E.2.1 Using syncx.SafeGroup

E.2.2 Exercises

E.3 Unbuffered channels

E.3.1 Usage

E.3.2 Synchronization

E.3.3 Pattern: Sending and receiving

E.4 Closing channels

E.4.1 Pattern: for-range

E.4.2 Pattern: Coordinating with a closing signal

E.5 Using the select statement

E.5.1 Waiting for multiple channels

E.5.2 Pattern: Nonblocking operations

E.6 Buffered channels

E.6.1 Pattern: Timing out

E.6.2 Directional channels