Skip to content

Locking Primitives

Overview

Locking primitives are the foundation of synchronization in Linux systems.

They provide coordination between concurrent execution contexts and protect shared resources from race conditions.

Different locking mechanisms solve different classes of synchronization problems.

Understanding their design goals and trade-offs is more important than memorizing individual APIs.


Synchronization Problem Categories

Most synchronization problems fall into one of the following categories.

Mutual Exclusion

Only one execution context may access or modify shared data at a time.

Examples:

Configuration update
Linked list modification
Device state update

Typical solution:

Mutex
Spinlock

Event Notification

One execution context waits for a condition generated by another execution context.

Examples:

Producer-consumer queue
Worker thread wakeup
State transition notification

Typical solution:

Condition Variable
Semaphore
Eventfd

Read-Mostly Access

Read operations are significantly more frequent than write operations.

Examples:

Routing table
Configuration table
Device lookup table

Typical solution:

RWLock
Seqlock
RCU

Condition Variable

Purpose

A condition variable allows a thread to wait until a specific condition becomes true.

Unlike a mutex, a condition variable does not protect data directly.

Instead, it provides an efficient waiting mechanism.


Typical Pattern

Acquire Mutex
Check Condition
Wait if Condition Not Met
Wakeup
Recheck Condition

Best Use Cases

Producer-consumer queues
State transitions
Task synchronization

Futex

Purpose

Futex (Fast Userspace Mutex) provides the foundation for most Linux userspace locking primitives.

The uncontended path executes entirely in userspace.

Kernel involvement occurs only when blocking is required.


Design Goal

Fast Path
Userspace Only

Slow Path
Kernel Wait Queue

Used By

pthread mutex
pthread condition variable
pthread rwlock

Reader-Writer Lock

Purpose

Allow multiple readers to access shared data simultaneously while preserving exclusive access for writers.


Design

Multiple Readers

Multiple Writers

Reader + Writer

Advantages

Higher read concurrency
Simple programming model

Disadvantages

Writer starvation may occur
Reader-side locking overhead remains

Best Use Cases

Read-heavy workloads
Configuration tables
Lookup structures

Comparison

Primitive Multiple Readers Writer Exclusion Blocking Typical Use
Mutex No Yes Yes Shared mutable state
Condition Variable N/A Uses mutex Yes Event waiting
Futex Depends on implementation Depends on implementation Yes Userspace synchronization foundation
RWLock Yes Yes Yes Read-heavy workloads

Relationship to Later Topics

RWLock improves concurrency by allowing multiple readers.

However, readers still perform locking operations.

More advanced synchronization mechanisms attempt to reduce reader overhead further:

RWLock
Seqlock
RCU

These mechanisms are covered in later topics.

Next Topics

  • Seqlock
  • RCU