The important difference is in purpose, not implementation. Most async runtimes use a thread or more per core, and the OS is doing that thread scheduling, so it's not the either-or situation that you describe.
The interesting thing about async (especially async-await) is that it is a fluent way to write a program that waits for events (e.g. I/O), without resorting to inefficient designs like thread-per-client in order to achieve concurrency.
Software (even in C) has made use of this concept for a long time through poll() and friends; async-await is just a higher level abstraction over the same concept.
> The important difference is in purpose, not implementation.
I couldn't disagree stronger on that one.
Abstraction is generally good, but this becomes a purely philosophical discussion as soon as you ignore the actual implementation when talking about the differences of how something actuals behaves and should be used. And philosophical discussions like that have their place but are imo pointless in the context of what should be used, when. They're generally better placed in a context of deciding wherever you want to implement an abstraction
I do fundamentally agree with the rest of your comment however.
that's what I meant with trusting your language to prioritize workloads vs your OS.
I'm not saying that implementation doesn't matter. I'm saying that that there isn't a fundamental implementation difference "async" vs "threads". Threads are used in both cases. It's a different choice of abstractions over the same underlying concepts.
FYI, Rust (the language) has no concept of prioritising workloads; there is no async runtime in the language.
Even with any of the async runtimes, workloads (i.e. tasks doing work) are prioritised by the OS. It's just threads executing code. Async runtimes are primarily concerned with the gaps between work, like waiting for I/O or other events.
The interesting thing about async (especially async-await) is that it is a fluent way to write a program that waits for events (e.g. I/O), without resorting to inefficient designs like thread-per-client in order to achieve concurrency.
Software (even in C) has made use of this concept for a long time through poll() and friends; async-await is just a higher level abstraction over the same concept.