Definition
Peterson’s algorithm is a simple software-only algorithm for mutual exclusion between two threads.
Core idea
- Thread
isetsflag[i] = trueand then setsturn = other. - It waits while
flag[other] && turn == other. - If both threads compete at the same time, the
turnvariable decides who waits.
Properties
- It guarantees mutual exclusion, progress, and bounded waiting for two threads under sequential consistency.
- It is simpler and cleaner than Dekker‘s algorithm, but today it is mostly of theoretical interest.
Entry and exit protocol
For thread i with other = 1 - i:
- entry:
- set
flag[i] = true - set
turn = other - wait while
flag[other] && turn == other
- set
- exit:
- set
flag[i] = false
- set
If both threads want to enter at the same time, both raise their flags, but the last write to turn gives priority to one thread and forces the other to wait.
Java example
public final class PetersonLock {
private final boolean[] flag = new boolean[2];
private volatile int turn;
public void lock(int i) {
int other = 1 - i;
flag[i] = true;
turn = other;
while (flag[other] && turn == other) {
Thread.onSpinWait();
}
}
public void unlock(int i) {
flag[i] = false;
}
}Usage:
PetersonLock lock = new PetersonLock();
// thread 0
lock.lock(0);
try {
// critical section
} finally {
lock.unlock(0);
}
// thread 1
lock.lock(1);
try {
// critical section
} finally {
lock.unlock(1);
}Extension to n threads: Filter lock
One extension of Peterson’s idea to n threads is the filter lock.
- Threads pass through levels
1,2,...,n-1 - at each level, one thread is marked as the
victim - a thread waits if it is still the victim and some other thread is at the same or a higher level
import java.util.concurrent.atomic.AtomicIntegerArray;
class FilterLock {
AtomicIntegerArray level;
AtomicIntegerArray victim;
volatile int n;
FilterLock(int n) {
this.n = n;
level = new AtomicIntegerArray(n);
victim = new AtomicIntegerArray(n);
}
// ∃k ≠ me: level[k] >= i (lev)
boolean Others(int me, int lev) {
for (int k = 0; k < n; ++k)
if (k != me && level.get(k) >= lev) return true;
return false;
}
public void Acquire(int me) {
for (int lev = 1; lev < n; ++lev) {
level.set(me, lev);
victim.set(lev, me);
while (me == victim.get(lev) && Others(me, lev));
}
}
public void Release(int me) {
level.set(me, 0);
}
}Important
Filter lock extends Peterson’s algorithm from
2threads tonthreads.