You should use an async Mutex only if you need to hold the lock across an .await. Otherwise you should use a regular Mutex from std or parking_lot. You should certainly not busy-loop like your code does.
Didn't think about that. Using synchronous Mutex inside an async environment could easily create deadlocks(*). So it seems that solution 2 (the busy loop) or something similar is always preferable.
(*)
runtime is executing future A that locks the sync Mutex
runtime stop future A for some reason and start executing future B
The busy loop is never preferable, I'm not sure where you got that from.
Note that, within Rust, the runtime will never stop the future unless you use a .await. If you need to use a mutex which you lock, and then do a .await before unlocking, you should use an async Mutex (from async_std or tokio, for instance).
If you don't need to .await while the Mutex is locked, you should prefer a sync Mutex from std or parking_lot, as that will generally give you the best multithreaded performance cooperating with the operating system.
The one uncommon use case cited above is when you have extremely computationally intensive work (i.e. something that takes close to a second to complete) you need to do while the Mutex is locked, at which point an async Mutex might again become preferable, to avoid blocking other Futures on other threads. This use case actually causes some more complicated implications on an async executor, so should be considered in further detail if you actually need it.
If I can't use an async Mutex (cause a need it in a impl trait that is not async). I could use the sync Mutex without risking any deadlock cause the lock is acquired and released in the syncrounous block that can never call .await so I'm 100% sure that the runtime will never stop before I release the lock.