Trylock
try_lock is a non-blocking variant of lock(): it attempts to acquire the mutex and returns immediately with a success/failure flag instead of parking the thread. Common in Rust, C++ (std::mutex::try_lock), POSIX (pthread_mutex_trylock), and Java (ReentrantLock.tryLock).
Why use it?
A blocking
lock()forces a context switch if the lock is contended, which is exactly what kicks off a lock convoy.try_locklets the caller decide what to do on failure: yield, back off, skip the work, or escalate to a blocking acquire.
Uses:
- Breaking deadlock hold-and-wait. If a thread already holds lock A and needs B, calling
try_lock(B)and releasing A on failure breaks the hold-and-wait Coffman condition - Avoiding lock convoys. Retry a bounded number of times with
thread::yield_now()between attempts, then fall back tolock(). Even a retry limit of 2 lets threads recover without convoy formation - Opportunistic work. “If I can grab the lock right now, do the thing; otherwise skip it.” Useful for best-effort caching, metrics updates, non-critical cleanup
Rust retry-then-fallback pattern (from ECE459 L12):
let mut retries = 0;
let retries_limit = 10;
let counter = Mutex::new(0);
loop {
if retries < retries_limit {
let mut l = counter.try_lock();
if l.is_ok() { *l.unwrap() = 1; break; }
else { retries += 1; thread::yield_now(); }
} else { *counter.lock().unwrap() = 1; break; }
}Spurious failures
POSIX
pthread_mutex_trylockand some implementations are allowed to fail even when the lock is available (e.g. under contention on the internal state). Treat failure as “try again later,” not “definitely held by someone else.”