I am not saying threads are the model for all programming problems. For example a dependency graph like an excel spreadsheet can be analyzed and parallelized.

But as you observed, async/await fails to express concurrency any better. It’s also a thread, it’s just a worse implementation.

That’s incorrect. Even when expressed suboptimally, it still tends to result in overall higher throughput and consistently lower latency (work stealing executors specifically). And when you’re in this world, you can always do an optimization pass to better express the concurrency. If you’ve not written it async to start with, then you’re boned and have no easy escape hatch to optimize with.

Why can’t you do the same optimization? Are you maxing out you OS system resources on thread overhead?

That’s part of it. Then you add a thread pool to dispatch your tasks into to mitigate the cost of a thread start. Then you run into blocking problems and are like “I wish I had some keyword to express when a function needed to be run on the thread pool”. Then you’ve done a speed run of the past 40 years of research.

The 40 years of research was actually in OS theory so that you could write normal code and async was abstracted away.

A thread pool is not a research project.

Although they can be used in similar ways they work very differently.

* Cooperative vs. preemptive scheduling

* Userspace vs. kernel scheduling

* Stackless vs. stackful

* Easy control over waiting/blocking behavior vs. none

* Easy fan out + join vs. maybe, with some work and thread spawn overhead

* Can integrate within a single-threaded event loop vs. not really

Depending on what you're doing they may be interchangeable or you can only go one way. The basic cases where you're doing basically synchronous work in a thread/task is no different either way, other than having colored functioned with async/await and efficiency. If you're doing some UI work then event handlers are likely running in a single-threaded event loop which is the only thread you can interact with the UI on, which you can't block or the UI is going to freeze.

OS thread overhead can be pretty substantial. Starting new threads on Windows is especially expensive.