132 / 163 · C11 · 8 min
Locks
Locks let programmers protect critical sections so that updates to shared data occur atomically, avoiding race conditions among concurrent threads.
In this lesson
Protecting Shared Updates with Locks
Programmers invoke lock acquire and release around sensitive code. This makes the enclosed operations appear atomic to other threads. The lock variable records whether it is free or held by a single thread.
Fine-grained versus Coarse-grained Locking
A single global lock forces every critical section to run serially. Independent locks for distinct data structures raise parallelism by allowing unrelated operations to proceed together.
Hardware and OS Support for Lock Implementation
Efficient locks rely on atomic read-modify-write instructions supplied by the processor together with operating-system facilities that put a thread to sleep instead of spinning while a lock is held.
Limitations of the Interrupt-Masking Approach
Turning interrupts off works solely on a uniprocessor and grants user programs too much privilege; a buggy or hostile program can render the system unresponsive to hardware events.
Pitfalls
- Omitting the unlock call leaves waiting threads blocked forever.
- Performing a potentially sleeping operation while a lock is held readily produces deadlock.
Run an example
Minimum C11 · complete program · Download .c
#include <stdio.h>
#include <pthread.h>
static int shared_counter = 0;
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static void *worker(void *arg) { (void)arg;
(void)arg;
for (int i = 0; i < 5000; ++i) {
pthread_mutex_lock(&mtx);
++shared_counter;
pthread_mutex_unlock(&mtx);
}
return NULL;
}
int main(void) {
pthread_t t1, t2;
pthread_create(&t1, NULL, worker, NULL);
pthread_create(&t2, NULL, worker, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Shared counter is %d\n", shared_counter);
return 0;
}
Compile locally
gcc -std=c11 -Wall -Wextra -Wpedantic -Werror -pthread ostep-28-locks.c -o example && ./exampleExpected result
Shared counter is 10000
CHECK YOUR UNDERSTANDING
Close the answer. Explain it.
Why can a lock built from an ordinary flag variable not guarantee mutual exclusion?
Show a reference answer
The test that the flag is free and the following store that marks it occupied can be interrupted, allowing several threads to enter the critical section at once.
Check the sources
Drafts and official chapters change. The version mark is only the example’s minimum.