Interactive stories -Coroutine Basics
Hi,
In this guide, we will introduce Kotlin Coroutines. You can try Kotlin code examples directly on Kotlin playground to make this more interactive. We will code together because, without hands-on practice, it might remain just theoretical.
Stay with me and let’s dive in!
When the world was a cloud of dust ;)
Fundamentally, understanding two key concepts in operating systems was crucial: processes and threads.
A process is an instance of a program currently being executed by the operating system which includes program code, data, and system resources.
A thread, on the other hand, is the entity that executes instructions and tasks within a process, consuming these resources.
Let’s explore threads further.
A thread describes in which context a sequence of instructions should be executed. Each thread has a specific task to perform.
Imagine a process as a basketball match. Just like each team in the game performs various tasks, each team can be seen as a thread that consumes resources and executes tasks.
If you observe closely, pressing a play button will demonstrate that both teams play on separate threads.
Blocking and non-blocking operations
In coding, instructions are executed sequentially, meaning each operation waits for the previous one to finish, known as a synchronous operation. For example, if an opponent commits a foul, you may get free throws. While you take these shots, all players must wait until you finish — this is called a blocking operation, where your actions can temporarily block others.
In the above, the running code didn’t finish during the delay, as the player blocked the main thread with synchronized programming.
Ideally, each team should play on a different thread for concurrent play, especially during extended game times. If a new thread isn’t created, actions may block the main thread, potentially causing errors. Just like teams can’t play simultaneously on the same court, thread allow teams to play concurrently without blocking the main thread.
In other words, in long-running operations such as network calls, image loading, and file operations, you need to work on a new thread. This new thread works parallel, asynchronous, with the main thread, your operations. This programming style is called non-blocking, asynchronous, etc.
If you run the code block, you’ll observe that the long-running operation starts and allows the next instructions to proceed while it continues in the background.
Why we need coroutines?
As you’ve seen, working with multiple threads, known as multi-threading, can be challenging. You must manage thread switching carefully to avoid memory leaks, and the number of threads available is limited by your platform. Moreover, threads consume CPU resources, which must be used judiciously. In contrast, coroutines offer a solution to these challenges.
What is a coroutine?
- A coroutine is mainly an instance of a suspendable computation. Suspend means that suspend(pause) a coroutine at some point and resume it in the future.
- Coroutines are executed within a thread and they are designed to manage threads. They can be likened to lightweight threads, each acting as a cooperative team player in the program
- Co-routine means that the program works with corporations and concurrency. Each team player playing with concurrency. They play asynchronous (parallel). So they don’t block each other.
Understanding suspend functions
Coroutines introduce the ability to suspend a coroutine at some point and resume it in the future. They also enable starting a suspend function in one thread and continuing it in another. For instance, when making API calls within a suspend function, the function pauses until a response is received, allowing other instructions to proceed without blocking the main thread. Once the response arrives, the suspend function resumes execution.
If you press play in the Kotlin playground, you’ll notice the network call starts and suspends until a response is received. Additionally, ‘launch’ is another coroutine builder that we’ll discuss later.
Let’s set our basketball game with coroutines:
Let’s visualize our basketball game with coroutines. Imagine players as coroutines assigned tasks like shooting, passing, dribbling, and positioning. Players operate asynchronously and cooperatively, much like a team.
This fictionalized game illustrates suspended players in various states — some positioning, others dribbling — while gameplay continues concurrently. Each player operates within their coroutine, contributing to team efforts. Press play to see the game unfold.
Conclusion
Throughout my career, I’ve emphasized the importance of understanding the theoretical aspects of programming. The concept of Coroutine has become a frequently used structure in software development. To understand the main idea of Coroutine, you need to ask “What is..?” until you reach the root knowledge. The coroutine is based on threads. The better you know thread logic, the easier it will be for you to understand Coroutine.
I encourage you to try running the code on the playground to further internalize coroutines.
See you on the next topic!