Can a single-threaded program be asynchronous?

A program is said to be single-threaded if it executes one instruction/sequence at a time. The single-threaded programs follow the “serial execution method” or “sequential execution approach.” All the instructions are executed by a single thread called the main thread.

In single-threaded programs, there is no concept of concurrent execution or parallelism. These programs are easy to reason with and simple as the instructions are executed sequentially.

What does asynchronous mean?

Asynchronous means a program can work or execute another sequence of instructions while one of the sequences waits. It is responsive and lets the other instructions manage instead of making them starve. There are different approaches to creating a program asynchronous, like using callbacks, promises, or routines.

An important thing to notice is that asynchronous doesn't mean multi-threaded programming.

An important thing to notice is that asynchronous doesn't mean multi-threaded programming.

Before diving into how a single-threaded program can be made asynchronous, we must clearly understand how asynchronous programming differs from synchronous programming.

Asynchronous Programming

Synchronous Programming

Tasks are executed cocurrently and independently

Tasks are executed one after another in a sequential manner

Tasks can start, pause, and resume their execution without waiting for other tasks to complete

Each task must complete before the program moves on to the next task

Code can be more complex to write and reason about due to the asynchronous nature of task execution.

Typically easier to reason about as the flow of execution is straightforward and follows a predictable order

Making a single-threaded program asynchronous

  • Event-driven programming: A single-threaded program can be made asynchronously using event handlers and trigger events. An asynchronous task is initiated, and the program executes the rest of the instructions while the asynchronous task is completed. As soon as this asynchronous task is finished, it will trigger an event handled by the handler. This allows the execution of multiple sequence instructions without waiting for one or blocking the rest.

  • Coroutine-based programming: Coroutines are supported by some programming frameworks, including Python. They offer a more synchronous style of execution, allowing routines to be paused and resumed without blocking other instructions.

Example of asynchronous programming

The asyncio module is a framework for writing asynchronous code using coroutines, tasks, and event loops. The provided code is an example of asyncio based code in Python.

import asyncio
async def asynchronous_task(name, delay):
print(f'Starting {name}')
await asyncio.sleep(delay)
print(f'Finished {name}')
@asyncio.coroutine
def main():
print('Main program started')
# Create and schedule multiple asynchronous tasks
task1 = asyncio.ensure_future(asynchronous_task('Task 1', 2))
task2 = asyncio.ensure_future(asynchronous_task('Task 2', 1))
# Continue executing other tasks while waiting for the asynchronous tasks to complete
print('Continuing with other tasks')
# Wait for the completion of all tasks
yield from asyncio.gather(task1, task2)
print('Main program finished')
# Create an event loop and run the main function
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

Explanation

  • Line 36: The asynchronous_task function represents an asynchronous operation that performs some work for a given duration specified by the delay parameter. The main function serves as the entry point for the program.

  • Line 922: Within the main function, there are two tasks (task1 and task2) which are created using the asyncio.create_task function. These tasks are scheduled to run concurrently. After creating the tasks, the program executes other tasks or operations without waiting for the asynchronous tasks to complete.

  • Line 20: The program then used asyncio.gather to wait to complete all tasks. The await keyword is used to wait for the call's completion, which ensures that the program does not proceed further until both tasks have finished.

When you run this code, you'll see that the tasks start executing without waiting for each other to finish. The program continues executing other tasks, and once all the jobs are complete, the "Main program finished" message is printed.

Conclusion

A single-threaded program can be asynchronous. Being asynchronous does not mean it is multi-threaded. It is still a single-threaded program, allowing multiple instructions to execute concurrently without waiting for the previous ones to complete.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved