In this chapter, we covered various design patterns related to concurrency in Kotlin. Most of them are based on coroutines, channels, deferred values, or a combination.
Pipeline, fan-in, and fan-out help distribute work and collect the results. Deferred values are used as placeholders for something that would resolve at a later time. Schedulers help us manage resources, mainly threads that back up the coroutines. Mutexes and Barriers help control that concurrency.
Now you should understand the select block and how it can be combined with channels and deferred values efficiently.
In the next chapter, we'll discuss Kotlin's idioms, best practices, and some of the anti-patterns that emerged with the language.