Synchronous programming
Whenever we make an API call or a database query, we need to wait for the request to travel over the network. This kind of task called I/O bound tasks.
With traditional synchronous programming, when a thread assigned to handle a task, it needs to standby and wait for the request to go over the network and come back.
This is a waste of resources because the thread is blocked and cannot handle any other tasks during the waiting. And with this programming, we usually use a pre-declared thread pool to handle multiple requests at the same time. However, if all threads inside the pool are busy, the system cannot accept any other requests and would drop them. Now, we have problems with scalability. This is where asynchronous (async) programming comes into play.
Asynchronous programming
With async programming, we don't block any threads for waiting I/O tasks. Instead, we have a main thread for accepting requests. These requests would be passed to the system to be run in background. So that, the main thread can continue accepting new requests without any blocking. When a task completed, the system would notify the main thread to continue with next steps.
With this, we don't need to have any thread-pool or so pre-declared. We don't need to concern about how big the pool should be to handle requests more efficiently. And by that, the source code would be much cleaner and easier to maintain or extend.
Example
Synchronous programming:
import time
def fetch_data():
print("Start fetching")
time.sleep(2) # simulates waiting for I/O
print("Done fetching")
return {"data": 123}
def main():
result = fetch_data()
print(result)
main()
The main thread has to wait 2 seconds before continuing with another request.
Asynchronous programming:
import asyncio
async def fetch_data():
print("Start fetching")
await asyncio.sleep(2) # simulates waiting for I/O
print("Done fetching")
return {"data": 123}
async def main():
result = await fetch_data()
print(result)
asyncio.run(main())
The main thread will not be blocked for 2 seconds, and can accept other requests immediately.
The await
keyword above would tell the system to pause the current task, put it in "pending" state while waiting for the I/O.
By that, the task will be moved out of the main thread stack. So, it can be available for upcoming requests.
Conclusions
Async programming is very helpful, especially when we are about to develop a GUI app like Web app or mobile app, where the main thread needs to be available as much as possible for handling UI rendering and reacting to user's input. All other tasks need to be put into background to avoid blocking the main thread. The main thread in this case sometimes called the UI thread for that reason.
Also, if our application has a lot of I/O tasks, we should consider apply async programming for better scale and easier maintenance.
Top comments (0)