Skip to main content

FairMutex

Type Alias FairMutex 

Source
pub type FairMutex<T> = Mutex<RawFairMutex, T>;
Expand description

A mutual exclusion primitive that uses fair unlocking, useful for protecting shared data.

This mutex will block threads waiting for the lock to become available. The mutex can be statically initialized or created by the new constructor. Each mutex has a type parameter which represents the data that it is protecting. The data can only be accessed through the RAII guards returned from lock and try_lock, which guarantees that the data is only ever accessed when the mutex is locked.

The regular mutex provided by parking_lot uses unfair unlocking by default, whereas this mutex always uses a fair unlock. When there are parked waiters, a fair unlock hands the mutex directly to one of them instead of making the mutex available for the unlocking thread to immediately re-acquire. Fair mutexes are generally slower, but can be useful when predictable handoff is more important than throughput.

Fair unlocking does not imply strict first-in first-out ordering: threads may acquire the mutex while spinning or through try_lock without joining the queue of parked waiters.

§Differences from the standard library Mutex

  • No poisoning, the lock is released normally on panic.
  • Only requires 1 byte of lock state.
  • Always uses fair unlocking.
  • Supports locking with a timeout.
  • Allows raw locking & unlocking without a guard.

§Examples

use parking_lot::FairMutex;
use std::sync::{Arc, mpsc::channel};
use std::thread;

const N: usize = 10;

// Spawn a few threads to increment a shared variable (non-atomically), and
// let the main thread know once all increments are done.
//
// Here we're using an Arc to share memory among threads, and the data inside
// the Arc is protected with a mutex.
let data = Arc::new(FairMutex::new(0));

let (tx, rx) = channel();
for _ in 0..N {
    let (data, tx) = (Arc::clone(&data), tx.clone());
    thread::spawn(move || {
        // The shared state can only be accessed once the lock is held.
        // Our non-atomic increment is safe because we're the only thread
        // which can access the shared state when the lock is held.
        let mut data = data.lock();
        *data += 1;
        if *data == N {
            tx.send(()).unwrap();
        }
        // the lock is unlocked here when `data` goes out of scope.
    });
}

rx.recv().unwrap();

Aliased Type§

pub struct FairMutex<T> { /* private fields */ }