UnboundedQueue Enqueue public void enq (T value) {
enqLock.lock();
try {
Node nd = new Node(value);
tail.next = nd;
tail = nd;
} finally {
enqLock.unlock();
}
}
LockFreeQueue Enqueue public void enq(T item) {
if (item == null) throw new NullPointerException();
Node node = new Node(item);
while (true) {
Node last = tail.get();
Node next = last.next.get();
if (last == tail.get()) {
if (next == null) {
if (last.next.compareAndSet(next, node))
tail.compareAndSet(last, node); return;
} else {
tail.compareAndSet(last, next);}}}}
UnboundedQueue ProgressGuarantee: Starvation Freedom (assuming lock is starvation-free)
if all pending method calls continue to take steps, then every pending method call completes in a finite number of steps
this is blocking progress: if even one thread stops taking steps, then all other threads can be impeded
Question. When is this “good?”
LockFreeQueue ProgressGuarantee: Lock Freedom
if some pending method call makes progress, then some pending method call completes in a finite number of steps
this is nonblocking progress: if some threads stall, others are still guaranteed to make progress
Blocking Progress:
Nonblocking Progress:
Demo: concurrent-queues.zip
class Peterson implements Lock {
private boolean[] flag = new boolean[2];
private int victim;
public void lock () {
int i = ThreadID.get(); int j = 1 - i;
flag[i] = true; // set my flag
victim = i; // set myself to be victim
while (flag[j] && victim == i) {}; }
public void unlock () { int i = ThreadID.get();
flag[i] = false; }
}
Download: peterson-lock.zip
Peterson lock assumes 2 threads, with IDs 0 and 1
We’ll use this thread to increment a counter
public class PetersonThread extends Thread {
private int id;
private LockedCounter ctr;
private int numIncrements;
public PetersonThread (id, ctr, numIncrements) {
super(); this.id = id; this.ctr = ctr;
this.numIncrements = numIncrements; }
public int getPetersonId() { return id; }
@Override
public void run () {
for (int i=0; i<numIncrements; ++i) { ctr.increment(); }}
}
Next week: A better way
PetersonLock
class PetersonLock {
private boolean[] flag = new boolean[2];
private int victim;
public void lock () {
int i = ((PetersonThread)Thread.currentThread())
.getPetersonId();
int j = 1 - i; flag[i] = true; victim = i;
while (flag[j] && victim == i) {};
}
public void unlock () {...}
}
public class LockedCounter {
private int count = 0;
PetersonLock lock = new PetersonLock();
public void increment () {
lock.lock();
try { ++count; }
finally { lock.unlock(); }
}
public int read () {
return count;
}
}
What happened?

volatile VariablesJava can make variables visible between threads:
volatile keywordvolatile are atomicDrawbacks:
volatile variables are less efficientcount++ not atomicvolatile SomeClass..., only the reference is treated as volatilevolatile?PetersonLock?
flag?victim?LockedCounter?
count?Only primitive datatypes can be volatile
volatile boolean[] flag makes the reference volatile, not the data itselfHow to fix this?
Just make 2 boolean variables, flag0 and flag1
peteson-lock.zipWhat have we done?
Theory and practice converge!
The Good:
The Bad:
PetersonThread to assign IDsQuestion. How could we lock more simply?
Use more advanced Atomic Objects!
Introducing the AtomicBoolean class:
var ab = new AtomicBoolean(boolean value) make an AtomicBoolean with initial value value
ab.get() return the current valueab.getAndSet(boolean newValue) atomically set the value to newValue and return the old valueab.compareAndSet(boolean expected, boolean new) atomically update to new if previous value was expected and return whether or not the value was updatedQuestion. How could we use AtomicBooleans to design a simpler lock?