that isn't a mutex, that's delegating work asynchronously and delegating something else to run when it is complete (the implicitly defined continuation through coroutines).
In systems programming parlance, a mutex is a resource which can be acquired and released, acquired exactly once, and blocks on acquire if already acquired.
it's a mutex iff it's acquiring a resource exclusively.
which you don't need to do for synchronization of coroutines since you can control in which order things are scheduled and whether that's done concurrently or not.
Not if you have multiple schedulers. Case in point: asio.strand or execution::on [1].
And even with one scheduler it makes sense to explicitly mark your critical sections.
Really, at the end of the day the primary purpose of a mutex is serialization of all operations on some data. The blocking behaviour is just a way to implement it.