Why does tokio's `current_thread` flavor not be single-threaded?

A minimum working example:

#[tokio::main(flavor = "current_thread")]
async fn main() {

tokio version: latest 1.22.0
Rust version: 1.65.0
OS: Ubuntu 22.04

After compiling this program, I run this binary under QEMU user-mode to log each instruction's tid, and find out that there are two threads in this application (and maybe it is because File::open calls spawn_blocking).

In tokio's doc, it is said that

To use the single-threaded runtime known as the current_thread runtime, the macro can be configured using flavor = "current_thread"

In my understanding, coroutine works as control flow is actively transmitted to runtime. I wonder why another thread is needed if I configured it to be current_thread.

spawn_blocking() has to use another thread to work as it is supposed to (prevent a blocking call from stopping the async execution), so if you want to have only one thread, you will need to avoid anything that uses spawn_blocking().


The current-thread runtime doesn't spawn additional threads to run async operations, but it will do so for spawn_blocking operation. The file system is not compatible with most ways of executing things asynchronously, so file operations are offloaded to the spawn_blocking threadpool.