6. For concurrency
beginners
Sorry
Please go to another room
For non-blocking
programming beginners
A short introduction
For advanced concurrent
programmers
CAS-based queue algorithm
7. You have another room!
12:10
Non-blocking Michael-
Scott queue algorithm
Alexey Fyodorov
Easily scale enterprise
applications
using distributed data grids
Ondrej Mihaly
9. Main Models
Shared Memory Messaging
write + read send + onReceive
Similar to how
we program it
Similar to how
a real hardware works
Distributed
Programming
Concurrent
Programming
15. Disadvantages of Locking
• Deadlocks
• Priority Inversion
• Reliability
• What will happen if lock owner die?
16. Disadvantages of Locking
• Deadlocks
• Priority Inversion
• Reliability
• What will happen if lock owner die?
• Performance
• Scheduler can push lock owner out
• No parallelism inside a critical section!
30. Example. Atomic Counter
AtomicLong value = new AtomicLong();
long get() {
return value.get();
}
void increment() {
long v;
do {
v = value.get();
} while (!value.compareAndSet(v, v + 1));
}
31. AtomicLong value = new AtomicLong();
long get() {
return value.get();
}
void increment() {
long v;
do {
v = value.get();
} while (!value.compareAndSet(v, v + 1));
}
Example. Atomic Counter
35. Non-blocking Guarantees
Wait-Free Per-thread progress is guaranteed
Lock-Free Overall progress is guaranteed
Obstruction-Free Overall progress is guaranteed
if threads don’t interfere with each other
36. CAS-loop
do {
v = value.get();
} while (!value.compareAndSet(v, v + 1));
A. Wait-Free
B. Lock-Free
C. Obstruction-Free
37. CAS-loop
do {
v = value.get();
} while (!value.compareAndSet(v, v + 1));
A. Wait-Free
B. Lock-Free
C. Obstruction-Free
*for modern hardware supporting CAS or LL/SC
85. public void put(E item) {
Node<E> newNode = new Node<>(item, null);
while (true) {
Node<E> currentTail = tail.get();
Node<E> tailNext = currentTail.next.get();
if (currentTail == tail.get()) {
if (tailNext != null) {
tail.compareAndSet(currentTail, tailNext);
} else {
if (currentTail.next.compareAndSet(null, newNode)) {
tail.compareAndSet(currentTail, newNode);
return;
}
}
}
}
}
86. public E poll() {
while (true) {
Node<E> first = head.get();
Node<E> last = tail.get();
Node<E> next = first.next.get();
if (first == head.get()) {
if (first == last) {
if (next == null) return null;
tail.compareAndSet(last, next);
} else {
E item = next.item;
if (head.compareAndSet(first, next))
return item;
}
}
}
}
95. Ladan-Mozes, Shavit, 2004, 2008
Key IDEA: use Doubly Linked List to avoid 2nd CAS
Optimistic Approach
http://people.csail.mit.edu/edya/publications/OptimisticFIFOQueue-journal.pdf
99. — Non-blocking algorithms are complicated
— Blocking algorithms are easier
— correctness checking is difficult
— difficult to support
— Sometimes it has better performance
Summary
100. — Non-blocking algorithms are complicated
— Blocking algorithms are easier
— correctness checking is difficult
— difficult to support
— Sometimes it has better performance
Summary
101. — Non-blocking algorithms are complicated
— Blocking algorithms are easier
— correctness checking is difficult
— difficult to support
— Sometimes it has better performance
Summary
Engineering is the art of trade-offs