Continuing the discussion from Help me choose a Mutex/RwLock ( parking_lot ? ):
Continuing the discussion from Things in std with strong alternatives:
See the link in @quinedot's post above for tracking issue #93740.
With all that information I'm still unsure what to do in my own programs. Use std::sync::Mutex
or parking_lot::Mutex
?
In the async
case where I need to hold a guard across an await
point, I will resort to an asynchronous mutex of course, such as tokio::sync::Mutex
.
But what if I lock the mutex only for a short time or in non-async programs? I'm particularly interested in cases where I use the mutex like a Send+Sync
variant of RefCell
, i.e. I know the mutex will never lock, but I need it to satisfy the compiler (without resorting to use unsafe
). Something like this:
#[tokio::main]
async fn main() {
let x = std::sync::Arc::new(std::sync::Mutex::new(0));
let x2 = x.clone();
tokio::spawn(async move {
*x2.lock().unwrap() += 1;
tokio::task::yield_now().await;
*x2.lock().unwrap() += 1;
}).await.unwrap();
println!("{}", x.lock().unwrap());
}
Which would work like a RefCell
, but if I used RefCell
, then I can't use tokio::spawn
but would have to use a local thread set:
#[tokio::main]
async fn main() {
let x = std::sync::Arc::new(std::cell::RefCell::new(0));
let x2 = x.clone();
tokio::task::LocalSet::new().run_until(async move {
tokio::task::spawn_local(async move {
*x2.borrow_mut() += 1;
tokio::task::yield_now().await;
*x2.borrow_mut() += 1;
}).await.unwrap();
}).await;
println!("{}", x.borrow());
}
I wonder how big is the overhead of std::sync::Mutex
and the lock-poisoning check? Is it neglectible even when I write a lot of values with this? (e.g. a lot of elements into a Vec
behind a mutex, where I acquire the lock each time I push a value)