asynchronous parallel programming
**Asynchronous Parallel Programming** is the **programming paradigm that enables concurrent execution without dedicating a thread to each concurrent activity — using futures/promises, async/await syntax, event loops, and coroutines to express parallelism in a way that scales to thousands or millions of concurrent operations (I/O requests, network calls, timers) without the memory overhead and context-switching cost of creating an equivalent number of OS threads**.
**The Thread Scalability Problem**
A web server handling 10,000 concurrent connections using one thread per connection needs 10,000 threads (10GB stack memory at 1MB each). Context switching 10,000 threads consumes significant CPU time. Async programming handles 10,000 connections with a handful of threads by suspending and resuming continuations as I/O completes.
**Key Abstractions**
- **Future/Promise**: A placeholder for a value that will be available later. `future = async_read(file)` returns immediately. The calling code can continue other work or await the result: `data = await future`. The runtime schedules the continuation when the I/O completes.
- **Async/Await**: Syntactic sugar for future-based programming. An `async` function returns a future. `await` suspends the function (without blocking the thread) until the awaited future resolves. The compiler transforms async functions into state machines that can be resumed.
- **Event Loop**: A single-threaded loop that monitors I/O readiness (select/epoll/kqueue) and dispatches callbacks for completed operations. Node.js, Python asyncio, and Rust tokio use event loops. The loop thread never blocks — all potentially blocking operations are async.
- **Coroutines**: Functions that can suspend execution and resume later from the suspension point. Cooperative multitasking — the coroutine explicitly yields control. Stackful coroutines (Go goroutines, fibers) save the entire call stack. Stackless coroutines (C++20 co_await, Rust async, Python generators) save only the local variables of the coroutine frame.
**Parallelism vs. Concurrency**
Async programming is fundamentally about concurrency (managing many in-flight operations) rather than parallelism (executing multiple computations simultaneously). However, async runtimes (Tokio, .NET ThreadPool, Java virtual threads) use a thread pool to execute ready tasks in parallel — combining async concurrency with multi-core parallelism.
**Language Implementations**
| Language | Async Mechanism | Runtime |
|----------|----------------|--------|
| Rust | async/await, zero-cost futures | Tokio, async-std (multi-threaded) |
| Python | asyncio, async/await | Single-threaded event loop + ProcessPoolExecutor |
| JavaScript/Node.js | Promises, async/await | libuv event loop (single-threaded + worker pool) |
| Go | goroutines + channels | Go scheduler (M:N threading) |
| Java 21+ | Virtual threads (Project Loom) | JVM scheduler (M:N) |
| C++20 | co_await, co_yield | User-provided executor |
**Structured Concurrency**
Modern async frameworks (Kotlin coroutines, Python TaskGroup, Swift async let) enforce structured concurrency — child tasks are bound to a parent scope. When the parent scope exits, all child tasks are awaited or cancelled. This prevents "fire and forget" leaks — orphaned concurrent tasks that run indefinitely.
Asynchronous Programming is **the scalability enabler for I/O-bound concurrent systems** — providing the programming abstractions that let a single machine handle millions of concurrent operations (network requests, database queries, file reads) without the overhead of millions of threads.