SlideShare a Scribd company logo
Non-blocking
Michael-Scott queue algorithm
Alexey Fyodorov
JUG.ru Group
• Programming
• Algorithms
• Concurrency
What is this talk about?
• Programming
• Algorithms
• Concurrency
Are	you	sure	you	need	it?
What is this talk about?
For concurrency
beginners
Sorry
Please go to another room
For concurrency
beginners
Sorry
Please go to another room
For non-blocking
programming beginners
A short introduction
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
You have another room!
12:10
Non-blocking Michael-
Scott queue algorithm
Alexey Fyodorov
Easily scale enterprise
applications
using distributed data grids
Ondrej Mihaly
Main Models
Shared Memory
write + read
Similar to how
we program it
Concurrent
Programming
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
Advantages of Parallelism
Resource utilization Utilization of several cores/CPUs
aka PERFORMANCE
Advantages of Parallelism
Resource utilization
Simplicity Complexity goes to magic frameworks
• ArrayBlockingQueue
• ConcurrentHashMap
• Akka
Utilization of several cores/CPUs
aka PERFORMANCE
Advantages of Parallelism
Resource utilization
Async handling
Simplicity
Utilization of several cores/CPUs
aka PERFORMANCE
Complexity goes to magic frameworks
• ArrayBlockingQueue
• ConcurrentHashMap
• Akka
Responsible services, Responsible UI
Disadvantages of Locking
• Deadlocks
Disadvantages of Locking
• Deadlocks
• Priority Inversion
Disadvantages of Locking
• Deadlocks
• Priority Inversion
• Reliability
• What will happen if lock owner die?
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!
Amdahl’s Law
α non-parallelizable part of the computation
1-α parallelizable part of the computation
p number of threads
Amdahl’s Law
α non-parallelizable part of the computation
1-α parallelizable part of the computation
p number of threads
S =	
#
α$	
%&α
'
If-Modify-Write
volatile int value = 0;
Can we run it
in multithreaded environment?
if (value == 0) {
value = 42;
}
If-Modify-Write
volatile int value = 0;
No atomicity
if (value == 0) {
value = 42;
}
}
Compare-And-Set
int value = 0;
LOCK
if (value == 0) {
value = 42;
}
UNLOCK
Introducing a Magic Operation
value.compareAndSet(0, 42);
int value = 0;
Simulated CAS
long value;
synchronized long get() {
return value;
}
synchronized long compareAndSwap(long expected, long newValue) {
long oldValue = value;
if (oldValue == expected) {
value = newValue;
}
return oldValue;
}
synchronized boolean compareAndSet(long expected, long newValue) {
return expected == compareAndSwap(expected, newValue);
}
Simulated CAS
long value;
synchronized long get() {
return value;
}
synchronized long compareAndSwap(long expected, long newValue) {
long oldValue = value;
if (oldValue == expected) {
value = newValue;
}
return oldValue;
}
synchronized boolean compareAndSet(long expected, long newValue) {
return expected == compareAndSwap(expected, newValue);
}
Simulated CAS
long value;
synchronized long get() {
return value;
}
synchronized long compareAndSwap(long expected, long newValue) {
long oldValue = value;
if (oldValue == expected) {
value = newValue;
}
return oldValue;
}
synchronized boolean compareAndSet(long expected, long newValue) {
return expected == compareAndSwap(expected, newValue);
}
Simulated CAS
long value;
synchronized long get() {
return value;
}
synchronized long compareAndSwap(long expected, long newValue) {
long oldValue = value;
if (oldValue == expected) {
value = newValue;
}
return oldValue;
}
synchronized boolean compareAndSet(long expected, long newValue){
return expected == compareAndSwap(expected, newValue);
}
Compare and Swap — Hardware Support
compare-and-swap
CAS
load-link / store-conditional
LL/SC
cmpxchg ldrex/strex lwarx/stwcx
Atomics in JDK
AtomicReference
• ref.get()
• ref.compareAndSet(v1, v2)
• ...
AtomicLong
• i.get()
• i.compareAndSet(42, 43)
• i.incrementAndGet(1)
• i.getAndAdd(5)
• ...
java.util.concurrent.atomic
Atomics in JDK
AtomicReference
• ref.get()
• ref.compareAndSet(v1, v2)
• ...
AtomicLong
• i.get()
• i.compareAndSet(42, 43)
• i.incrementAndGet(1)
• i.getAndAdd(5)
• ...
java.util.concurrent.atomic
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));
}
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
Atomics.
Questions?
Non-blocking Guarantees
Wait-Free Per-thread progress is guaranteed
Non-blocking Guarantees
Wait-Free Per-thread progress is guaranteed
Lock-Free Overall progress is guaranteed
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
CAS-loop
do {
v = value.get();
} while (!value.compareAndSet(v, v + 1));
A. Wait-Free
B. Lock-Free
C. Obstruction-Free
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
Stack & Concurrency
class Node<E> {
final E item;
Node<E> next;
Node(E item) {
this.item = item;
}
}
...
class Node<E> {
final E item;
Node<E> next;
Node(E item) {
this.item = item;
}
}
E3
E1
E2
E3
E1
E2
top
E3
E1
E2
top
item1
Thread 1
E3
E1
E2
top
item1
Thread 1
E3
E1
E2
top
item2item1
Thread 1 Thread 2
E3
E1
E2
top
item2item1
Thread 1 Thread 2
E3
E1
E2
item2item1
Thread 1 Thread 2top
E3
E1
E2
item2item1
Thread 1 Thread 2
We need
a synchronization
top
Non-blocking Stack
void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
AtomicReference<Node<E>> top;
E3
E1
E2
top
void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
AtomicReference<Node<E>> top;
E3
E1
E2
item
top
void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
E3
E1
E2
item
AtomicReference<Node<E>> top;
top
newHead
void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
E3
E1
E2
AtomicReference<Node<E>> top;
item
top
newHead
oldHead
void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
AtomicReference<Node<E>> top;
E3
E1
E2
item
top
newHead
oldHead
void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
AtomicReference<Node<E>> top;
E3
E1
E2
item
top
newHead
oldHead
void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
AtomicReference<Node<E>> top;
E3
E1
E2
item
top
void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
AtomicReference<Node<E>> top;
E3
E1
E2
item
top
newHead
oldHead
void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
E3
E1
E2
AtomicReference<Node<E>> top;
top
itemnewHead
oldHead
void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
E3
E1
E2
AtomicReference<Node<E>> top;
top
item
E pop() {
Node<E> newHead;
Node<E> oldHead;
do {
oldHead = top.get();
if (oldHead == null) return null;
newHead = oldHead.next;
} while (!top.compareAndSet(oldHead, newHead));
return oldHead.item;
}
E3
E1
E2
top
Non-blocking Stack.
Questions?
Non-blocking Queue
Michael and Scott, 1996
https://www.research.ibm.com/people/m/michael/podc-1996.pdf
Threads help each other
Non-blocking queue
class LinkedQueue<E> {
static class Node<E> {
E item;
AtomicReference<Node<E>> next;
Node(E item, AtomicReference<Node<E>> next) {
this.item = item;
this.next = next;
}
}
Node<E> dummy = new Node<>(null, null);
AtomicReference<Node<E>> head = new AtomicReference<>(dummy);
AtomicReference<Node<E>> tail = new AtomicReference<>(dummy);
}
class LinkedQueue<E> {
static class Node<E> {
E item;
AtomicReference<Node<E>> next;
Node(E item, AtomicReference<Node<E>> next) {
this.item = item;
this.next = next;
}
}
Node<E> dummy = new Node<>(null, null);
AtomicReference<Node<E>> head = new AtomicReference<>(dummy);
AtomicReference<Node<E>> tail = new AtomicReference<>(dummy);
}
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.compareAndSet(null, newNode);
tail.compareAndSet(curTail, curTail.next.get());
} while (!success);
}
tail
dummy 1 2
head
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.compareAndSet(null, newNode);
tail.compareAndSet(curTail, curTail.next.get());
} while (!success);
}
tail
dummy 1 2 item
head
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.compareAndSet(null, newNode);
tail.compareAndSet(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNode
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.compareAndSet(null, newNode);
tail.compareAndSet(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.compareAndSet(null, newNode);
tail.compareAndSet(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.compareAndSet(null, newNode);
tail.compareAndSet(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.compareAndSet(null, newNode);
tail.compareAndSet(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.compareAndSet(null, newNode);
tail.compareAndSet(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.CAS(null, newNode);
tail.CAS(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.CAS(null, newNode);
tail.CAS(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.CAS(null, newNode); // true
tail.CAS(curTail, curTail.next.get()); // true
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.CAS(null, newNode);
tail.CAS(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.CAS(null, newNode); // true
tail.CAS(curTail, curTail.next.get()); // false
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.CAS(null, newNode);
tail.CAS(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.CAS(null, newNode); // false
tail.CAS(curTail, curTail.next.get()); // false
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
another
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.CAS(null, newNode);
tail.CAS(curTail, curTail.next.get());
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.CAS(null, newNode); // false
tail.CAS(curTail, curTail.next.get()); // true
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
another
void put(E item) {
Node<E> newNode = new Node<>(item, null);
boolean success;
do {
Node<E> curTail = tail.get();
success = curTail.next.CAS(null, newNode); // false
tail.CAS(curTail, curTail.next.get()); // true
} while (!success);
}
tailhead
dummy 1 2 item
newNodecurTail
anotherHELP
Synchronization
Blocking
lock + unlock
Invariant: before & after
lock-based
Synchronization
Blocking Non-blocking
lock + unlock CAS-loop
Invariant: before & after Semi-invariant
CAS-basedlock-based
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;
}
}
}
}
}
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;
}
}
}
}
Non-blocking Queue in JDK
ConcurrentLinkedQueue is
based on Michael-Scott queue
— based on CAS-like operations
— use CAS-loop pattern
— threads help one another
Non-blocking algorithms. Summary
Non-blocking Queue.
Questions?
ArrayBlockingQueue
ArrayBlockingQueue
0 1 2 3 4 N-1
...
void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
} finally {
lock.unlock();
}
}
ArrayBlockingQueue.put()
void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
} finally {
lock.unlock();
}
}
ArrayBlockingQueue.put()
Modifications
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
Hoffman, Shalev, Shavit, 2007
Baskets	Queue
http://people.csail.mit.edu/shanir/publications/Baskets%20Queue.pdf
— Throughput is better
— no FIFO any more
— usually you don’t need strong FIFO in real life
Baskets Queue
Summary
— Non-blocking algorithms are complicated
— Blocking algorithms are easier
— correctness checking is difficult
— difficult to support
— Sometimes it has better performance
Summary
— Non-blocking algorithms are complicated
— Blocking algorithms are easier
— correctness checking is difficult
— difficult to support
— Sometimes it has better performance
Summary
— 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
Links & Books
Books
Links
• Nitsan Wakart — http://psy-lob-saw.blogspot.com/	
• Alexey	Shipilev— https://shipilev.net/	
• concurrency-interest	mailing	list:	
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Q & A

More Related Content

What's hot (20)

PDF
Plpgsql internals
Pavel Stěhule
 
PPTX
From distributed caches to in-memory data grids
Max Alexejev
 
PDF
Apache Kafka Architecture & Fundamentals Explained
confluent
 
PDF
Introduction to Spring Boot!
Jakub Kubrynski
 
PDF
Introduction to Apache Kafka
Shiao-An Yuan
 
PDF
Handle Large Messages In Apache Kafka
Jiangjie Qin
 
PDF
Fundamentals of Apache Kafka
Chhavi Parasher
 
PDF
MySQL InnoDB Cluster - A complete High Availability solution for MySQL
Olivier DASINI
 
PDF
Swagger UI
Walaa Hamdy Assy
 
PPTX
Beyond REST and RPC: Asynchronous Eventing and Messaging Patterns
Clemens Vasters
 
PDF
Oracle Golden Gate Interview Questions
Arun Sharma
 
PDF
MySQL Cluster performance best practices
Mat Keep
 
PDF
Unsafe JAX-RS: Breaking REST API
Mikhail Egorov
 
PDF
Leverage CompletableFutures to handle async queries. DevNexus 2022
David Gómez García
 
PPTX
Kafka and Avro with Confluent Schema Registry
Jean-Paul Azar
 
PDF
Neural Search Comes to Apache Solr_ Approximate Nearest Neighbor, BERT and Mo...
Sease
 
PDF
Magento 2 Design Patterns
Max Pronko
 
PDF
Kafka 101 and Developer Best Practices
confluent
 
PPTX
Getting the most out of MariaDB MaxScale
MariaDB plc
 
PDF
Jakarta EE 10 - Simplicity for Modern and Lighweight Cloud
Ivar Grimstad
 
Plpgsql internals
Pavel Stěhule
 
From distributed caches to in-memory data grids
Max Alexejev
 
Apache Kafka Architecture & Fundamentals Explained
confluent
 
Introduction to Spring Boot!
Jakub Kubrynski
 
Introduction to Apache Kafka
Shiao-An Yuan
 
Handle Large Messages In Apache Kafka
Jiangjie Qin
 
Fundamentals of Apache Kafka
Chhavi Parasher
 
MySQL InnoDB Cluster - A complete High Availability solution for MySQL
Olivier DASINI
 
Swagger UI
Walaa Hamdy Assy
 
Beyond REST and RPC: Asynchronous Eventing and Messaging Patterns
Clemens Vasters
 
Oracle Golden Gate Interview Questions
Arun Sharma
 
MySQL Cluster performance best practices
Mat Keep
 
Unsafe JAX-RS: Breaking REST API
Mikhail Egorov
 
Leverage CompletableFutures to handle async queries. DevNexus 2022
David Gómez García
 
Kafka and Avro with Confluent Schema Registry
Jean-Paul Azar
 
Neural Search Comes to Apache Solr_ Approximate Nearest Neighbor, BERT and Mo...
Sease
 
Magento 2 Design Patterns
Max Pronko
 
Kafka 101 and Developer Best Practices
confluent
 
Getting the most out of MariaDB MaxScale
MariaDB plc
 
Jakarta EE 10 - Simplicity for Modern and Lighweight Cloud
Ivar Grimstad
 

Similar to Non-blocking Michael-Scott queue algorithm (20)

PDF
Non-blocking synchronization — what is it and why we (don't?) need it
Alexey Fyodorov
 
PDF
无锁编程
vorfeed chen
 
PDF
Lock free algorithms
Pan Ip
 
PPTX
Introduction to Concurrent Data Structures
Dilum Bandara
 
PPT
Hs java open_party
Open Party
 
PDF
Concurrency
Isaac Liao
 
PDF
Lockless
Sandeep Joshi
 
PDF
Java Concurrency in Practice
Alina Dolgikh
 
PDF
Scale Up with Lock-Free Algorithms @ JavaOne
Roman Elizarov
 
PPTX
Introduction to Concurrent Programming
Dilum Bandara
 
PDF
The Need for Async @ ScalaWorld
Konrad Malawski
 
PDF
Understanding the Disruptor
Trisha Gee
 
PDF
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
PROIDEA
 
PDF
jvm/java - towards lock-free concurrency
Arvind Kalyan
 
KEY
Java Core | Understanding the Disruptor: a Beginner's Guide to Hardcore Concu...
JAX London
 
PDF
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Mario Fusco
 
DOCX
Java 5 concurrency
priyank09
 
PDF
[JavaOne 2011] Models for Concurrent Programming
Tobias Lindaaker
 
PDF
Let's Talk Locks!
C4Media
 
PDF
Towards a Scalable Non-Blocking Coding Style
Azul Systems Inc.
 
Non-blocking synchronization — what is it and why we (don't?) need it
Alexey Fyodorov
 
无锁编程
vorfeed chen
 
Lock free algorithms
Pan Ip
 
Introduction to Concurrent Data Structures
Dilum Bandara
 
Hs java open_party
Open Party
 
Concurrency
Isaac Liao
 
Lockless
Sandeep Joshi
 
Java Concurrency in Practice
Alina Dolgikh
 
Scale Up with Lock-Free Algorithms @ JavaOne
Roman Elizarov
 
Introduction to Concurrent Programming
Dilum Bandara
 
The Need for Async @ ScalaWorld
Konrad Malawski
 
Understanding the Disruptor
Trisha Gee
 
Atmosphere Conference 2015: Need for Async: In pursuit of scalable internet-s...
PROIDEA
 
jvm/java - towards lock-free concurrency
Arvind Kalyan
 
Java Core | Understanding the Disruptor: a Beginner's Guide to Hardcore Concu...
JAX London
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Mario Fusco
 
Java 5 concurrency
priyank09
 
[JavaOne 2011] Models for Concurrent Programming
Tobias Lindaaker
 
Let's Talk Locks!
C4Media
 
Towards a Scalable Non-Blocking Coding Style
Azul Systems Inc.
 
Ad

More from Alexey Fyodorov (14)

PDF
How threads help each other
Alexey Fyodorov
 
PDF
Помоги ближнему, или Как потоки помогают друг другу
Alexey Fyodorov
 
PDF
Counter Wars (JEEConf 2016)
Alexey Fyodorov
 
PDF
Синхронизация без блокировок и СМС
Alexey Fyodorov
 
PDF
Unsafe: to be or to be removed?
Alexey Fyodorov
 
PDF
Общество Мертвых Потоков
Alexey Fyodorov
 
PDF
JDK: CPU, PSU, LU, FR — WTF?!
Alexey Fyodorov
 
PDF
Atomics, CAS and Nonblocking algorithms
Alexey Fyodorov
 
PDF
Philosophers
Alexey Fyodorov
 
PDF
Java in Motion
Alexey Fyodorov
 
PDF
Java Platform Tradeoffs (Riga 2013)
Alexey Fyodorov
 
PDF
Java Platform Tradeoffs (CEE SECR 2013)
Alexey Fyodorov
 
PDF
Процесс изменения платформы Java
Alexey Fyodorov
 
PPTX
Java: how to thrive in the changing world
Alexey Fyodorov
 
How threads help each other
Alexey Fyodorov
 
Помоги ближнему, или Как потоки помогают друг другу
Alexey Fyodorov
 
Counter Wars (JEEConf 2016)
Alexey Fyodorov
 
Синхронизация без блокировок и СМС
Alexey Fyodorov
 
Unsafe: to be or to be removed?
Alexey Fyodorov
 
Общество Мертвых Потоков
Alexey Fyodorov
 
JDK: CPU, PSU, LU, FR — WTF?!
Alexey Fyodorov
 
Atomics, CAS and Nonblocking algorithms
Alexey Fyodorov
 
Philosophers
Alexey Fyodorov
 
Java in Motion
Alexey Fyodorov
 
Java Platform Tradeoffs (Riga 2013)
Alexey Fyodorov
 
Java Platform Tradeoffs (CEE SECR 2013)
Alexey Fyodorov
 
Процесс изменения платформы Java
Alexey Fyodorov
 
Java: how to thrive in the changing world
Alexey Fyodorov
 
Ad

Recently uploaded (20)

PDF
13th International Conference of Security, Privacy and Trust Management (SPTM...
ijcisjournal
 
PPTX
Explore USA’s Best Structural And Non Structural Steel Detailing
Silicon Engineering Consultants LLC
 
PDF
CLIP_Internals_and_Architecture.pdf sdvsdv sdv
JoseLuisCahuanaRamos3
 
PPT
SF 9_Unit 1.ppt software engineering ppt
AmarrKannthh
 
DOCX
Engineering Geology Field Report to Malekhu .docx
justprashant567
 
PDF
FSE-Journal-First-Automated code editing with search-generate-modify.pdf
cl144
 
PDF
輪読会資料_Miipher and Miipher2 .
NABLAS株式会社
 
PPTX
ASBC application presentation template (ENG)_v3 (1).pptx
HassanMohammed730118
 
PDF
تقرير عن التحليل الديناميكي لتدفق الهواء حول جناح.pdf
محمد قصص فتوتة
 
PDF
Python Mini Project: Command-Line Quiz Game for School/College Students
MPREETHI7
 
PPTX
Introduction to File Transfer Protocol with commands in FTP
BeulahS2
 
PPTX
Bharatiya Antariksh Hackathon 2025 Idea Submission PPT.pptx
AsadShad4
 
PPTX
Comparison of Flexible and Rigid Pavements in Bangladesh
Arifur Rahman
 
PDF
01-introduction to the ProcessDesign.pdf
StiveBrack
 
PPTX
CST413 KTU S7 CSE Machine Learning Introduction Parameter Estimation MLE MAP ...
resming1
 
PDF
PRIZ Academy - Process functional modelling
PRIZ Guru
 
PPTX
FSE_LLM4SE1_A Tool for In-depth Analysis of Code Execution Reasoning of Large...
cl144
 
PPTX
CST413 KTU S7 CSE Machine Learning Neural Networks and Support Vector Machine...
resming1
 
PDF
Generative AI & Scientific Research : Catalyst for Innovation, Ethics & Impact
AlqualsaDIResearchGr
 
PPT
دراسة حاله لقرية تقع في جنوب غرب السودان
محمد قصص فتوتة
 
13th International Conference of Security, Privacy and Trust Management (SPTM...
ijcisjournal
 
Explore USA’s Best Structural And Non Structural Steel Detailing
Silicon Engineering Consultants LLC
 
CLIP_Internals_and_Architecture.pdf sdvsdv sdv
JoseLuisCahuanaRamos3
 
SF 9_Unit 1.ppt software engineering ppt
AmarrKannthh
 
Engineering Geology Field Report to Malekhu .docx
justprashant567
 
FSE-Journal-First-Automated code editing with search-generate-modify.pdf
cl144
 
輪読会資料_Miipher and Miipher2 .
NABLAS株式会社
 
ASBC application presentation template (ENG)_v3 (1).pptx
HassanMohammed730118
 
تقرير عن التحليل الديناميكي لتدفق الهواء حول جناح.pdf
محمد قصص فتوتة
 
Python Mini Project: Command-Line Quiz Game for School/College Students
MPREETHI7
 
Introduction to File Transfer Protocol with commands in FTP
BeulahS2
 
Bharatiya Antariksh Hackathon 2025 Idea Submission PPT.pptx
AsadShad4
 
Comparison of Flexible and Rigid Pavements in Bangladesh
Arifur Rahman
 
01-introduction to the ProcessDesign.pdf
StiveBrack
 
CST413 KTU S7 CSE Machine Learning Introduction Parameter Estimation MLE MAP ...
resming1
 
PRIZ Academy - Process functional modelling
PRIZ Guru
 
FSE_LLM4SE1_A Tool for In-depth Analysis of Code Execution Reasoning of Large...
cl144
 
CST413 KTU S7 CSE Machine Learning Neural Networks and Support Vector Machine...
resming1
 
Generative AI & Scientific Research : Catalyst for Innovation, Ethics & Impact
AlqualsaDIResearchGr
 
دراسة حاله لقرية تقع في جنوب غرب السودان
محمد قصص فتوتة
 

Non-blocking Michael-Scott queue algorithm

  • 2. • Programming • Algorithms • Concurrency What is this talk about?
  • 3. • Programming • Algorithms • Concurrency Are you sure you need it? What is this talk about?
  • 5. For concurrency beginners Sorry Please go to another room For non-blocking programming beginners A short introduction
  • 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
  • 8. Main Models Shared Memory write + read Similar to how we program it Concurrent Programming
  • 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
  • 10. Advantages of Parallelism Resource utilization Utilization of several cores/CPUs aka PERFORMANCE
  • 11. Advantages of Parallelism Resource utilization Simplicity Complexity goes to magic frameworks • ArrayBlockingQueue • ConcurrentHashMap • Akka Utilization of several cores/CPUs aka PERFORMANCE
  • 12. Advantages of Parallelism Resource utilization Async handling Simplicity Utilization of several cores/CPUs aka PERFORMANCE Complexity goes to magic frameworks • ArrayBlockingQueue • ConcurrentHashMap • Akka Responsible services, Responsible UI
  • 14. Disadvantages of Locking • Deadlocks • Priority Inversion
  • 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!
  • 17. Amdahl’s Law α non-parallelizable part of the computation 1-α parallelizable part of the computation p number of threads
  • 18. Amdahl’s Law α non-parallelizable part of the computation 1-α parallelizable part of the computation p number of threads S = # α$ %&α '
  • 19. If-Modify-Write volatile int value = 0; Can we run it in multithreaded environment? if (value == 0) { value = 42; }
  • 20. If-Modify-Write volatile int value = 0; No atomicity if (value == 0) { value = 42; } }
  • 21. Compare-And-Set int value = 0; LOCK if (value == 0) { value = 42; } UNLOCK
  • 22. Introducing a Magic Operation value.compareAndSet(0, 42); int value = 0;
  • 23. Simulated CAS long value; synchronized long get() { return value; } synchronized long compareAndSwap(long expected, long newValue) { long oldValue = value; if (oldValue == expected) { value = newValue; } return oldValue; } synchronized boolean compareAndSet(long expected, long newValue) { return expected == compareAndSwap(expected, newValue); }
  • 24. Simulated CAS long value; synchronized long get() { return value; } synchronized long compareAndSwap(long expected, long newValue) { long oldValue = value; if (oldValue == expected) { value = newValue; } return oldValue; } synchronized boolean compareAndSet(long expected, long newValue) { return expected == compareAndSwap(expected, newValue); }
  • 25. Simulated CAS long value; synchronized long get() { return value; } synchronized long compareAndSwap(long expected, long newValue) { long oldValue = value; if (oldValue == expected) { value = newValue; } return oldValue; } synchronized boolean compareAndSet(long expected, long newValue) { return expected == compareAndSwap(expected, newValue); }
  • 26. Simulated CAS long value; synchronized long get() { return value; } synchronized long compareAndSwap(long expected, long newValue) { long oldValue = value; if (oldValue == expected) { value = newValue; } return oldValue; } synchronized boolean compareAndSet(long expected, long newValue){ return expected == compareAndSwap(expected, newValue); }
  • 27. Compare and Swap — Hardware Support compare-and-swap CAS load-link / store-conditional LL/SC cmpxchg ldrex/strex lwarx/stwcx
  • 28. Atomics in JDK AtomicReference • ref.get() • ref.compareAndSet(v1, v2) • ... AtomicLong • i.get() • i.compareAndSet(42, 43) • i.incrementAndGet(1) • i.getAndAdd(5) • ... java.util.concurrent.atomic
  • 29. Atomics in JDK AtomicReference • ref.get() • ref.compareAndSet(v1, v2) • ... AtomicLong • i.get() • i.compareAndSet(42, 43) • i.incrementAndGet(1) • i.getAndAdd(5) • ... java.util.concurrent.atomic
  • 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
  • 34. Non-blocking Guarantees Wait-Free Per-thread progress is guaranteed Lock-Free Overall progress is guaranteed
  • 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
  • 39. class Node<E> { final E item; Node<E> next; Node(E item) { this.item = item; } } ...
  • 40. class Node<E> { final E item; Node<E> next; Node(E item) { this.item = item; } } E3 E1 E2
  • 47. E3 E1 E2 item2item1 Thread 1 Thread 2 We need a synchronization top
  • 49. void push(E item) { Node<E> newHead = new Node<>(item); Node<E> oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } AtomicReference<Node<E>> top; E3 E1 E2 top
  • 50. void push(E item) { Node<E> newHead = new Node<>(item); Node<E> oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } AtomicReference<Node<E>> top; E3 E1 E2 item top
  • 51. void push(E item) { Node<E> newHead = new Node<>(item); Node<E> oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } E3 E1 E2 item AtomicReference<Node<E>> top; top newHead
  • 52. void push(E item) { Node<E> newHead = new Node<>(item); Node<E> oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } E3 E1 E2 AtomicReference<Node<E>> top; item top newHead oldHead
  • 53. void push(E item) { Node<E> newHead = new Node<>(item); Node<E> oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } AtomicReference<Node<E>> top; E3 E1 E2 item top newHead oldHead
  • 54. void push(E item) { Node<E> newHead = new Node<>(item); Node<E> oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } AtomicReference<Node<E>> top; E3 E1 E2 item top newHead oldHead
  • 55. void push(E item) { Node<E> newHead = new Node<>(item); Node<E> oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } AtomicReference<Node<E>> top; E3 E1 E2 item top
  • 56. void push(E item) { Node<E> newHead = new Node<>(item); Node<E> oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } AtomicReference<Node<E>> top; E3 E1 E2 item top newHead oldHead
  • 57. void push(E item) { Node<E> newHead = new Node<>(item); Node<E> oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } E3 E1 E2 AtomicReference<Node<E>> top; top itemnewHead oldHead
  • 58. void push(E item) { Node<E> newHead = new Node<>(item); Node<E> oldHead; do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead)); } E3 E1 E2 AtomicReference<Node<E>> top; top item
  • 59. E pop() { Node<E> newHead; Node<E> oldHead; do { oldHead = top.get(); if (oldHead == null) return null; newHead = oldHead.next; } while (!top.compareAndSet(oldHead, newHead)); return oldHead.item; } E3 E1 E2 top
  • 62. Michael and Scott, 1996 https://www.research.ibm.com/people/m/michael/podc-1996.pdf Threads help each other Non-blocking queue
  • 63. class LinkedQueue<E> { static class Node<E> { E item; AtomicReference<Node<E>> next; Node(E item, AtomicReference<Node<E>> next) { this.item = item; this.next = next; } } Node<E> dummy = new Node<>(null, null); AtomicReference<Node<E>> head = new AtomicReference<>(dummy); AtomicReference<Node<E>> tail = new AtomicReference<>(dummy); }
  • 64. class LinkedQueue<E> { static class Node<E> { E item; AtomicReference<Node<E>> next; Node(E item, AtomicReference<Node<E>> next) { this.item = item; this.next = next; } } Node<E> dummy = new Node<>(null, null); AtomicReference<Node<E>> head = new AtomicReference<>(dummy); AtomicReference<Node<E>> tail = new AtomicReference<>(dummy); }
  • 65. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.compareAndSet(null, newNode); tail.compareAndSet(curTail, curTail.next.get()); } while (!success); } tail dummy 1 2 head
  • 66. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.compareAndSet(null, newNode); tail.compareAndSet(curTail, curTail.next.get()); } while (!success); } tail dummy 1 2 item head
  • 67. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.compareAndSet(null, newNode); tail.compareAndSet(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNode
  • 68. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.compareAndSet(null, newNode); tail.compareAndSet(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 69. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.compareAndSet(null, newNode); tail.compareAndSet(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 70. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.compareAndSet(null, newNode); tail.compareAndSet(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 71. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.compareAndSet(null, newNode); tail.compareAndSet(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 72. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.compareAndSet(null, newNode); tail.compareAndSet(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 73. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.CAS(null, newNode); tail.CAS(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 74. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.CAS(null, newNode); tail.CAS(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 75. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.CAS(null, newNode); // true tail.CAS(curTail, curTail.next.get()); // true } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 76. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.CAS(null, newNode); tail.CAS(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 77. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.CAS(null, newNode); // true tail.CAS(curTail, curTail.next.get()); // false } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 78. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.CAS(null, newNode); tail.CAS(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 79. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.CAS(null, newNode); // false tail.CAS(curTail, curTail.next.get()); // false } while (!success); } tailhead dummy 1 2 item newNodecurTail another
  • 80. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.CAS(null, newNode); tail.CAS(curTail, curTail.next.get()); } while (!success); } tailhead dummy 1 2 item newNodecurTail
  • 81. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.CAS(null, newNode); // false tail.CAS(curTail, curTail.next.get()); // true } while (!success); } tailhead dummy 1 2 item newNodecurTail another
  • 82. void put(E item) { Node<E> newNode = new Node<>(item, null); boolean success; do { Node<E> curTail = tail.get(); success = curTail.next.CAS(null, newNode); // false tail.CAS(curTail, curTail.next.get()); // true } while (!success); } tailhead dummy 1 2 item newNodecurTail anotherHELP
  • 84. Synchronization Blocking Non-blocking lock + unlock CAS-loop Invariant: before & after Semi-invariant CAS-basedlock-based
  • 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; } } } }
  • 87. Non-blocking Queue in JDK ConcurrentLinkedQueue is based on Michael-Scott queue
  • 88. — based on CAS-like operations — use CAS-loop pattern — threads help one another Non-blocking algorithms. Summary
  • 92. void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); final Object[] items = this.items; items[putIndex] = x; if (++putIndex == items.length) putIndex = 0; count++; notEmpty.signal(); } finally { lock.unlock(); } } ArrayBlockingQueue.put()
  • 93. void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); final Object[] items = this.items; items[putIndex] = x; if (++putIndex == items.length) putIndex = 0; count++; notEmpty.signal(); } finally { lock.unlock(); } } ArrayBlockingQueue.put()
  • 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
  • 96. Hoffman, Shalev, Shavit, 2007 Baskets Queue http://people.csail.mit.edu/shanir/publications/Baskets%20Queue.pdf
  • 97. — Throughput is better — no FIFO any more — usually you don’t need strong FIFO in real life Baskets Queue
  • 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
  • 103. Books
  • 104. Links • Nitsan Wakart — http://psy-lob-saw.blogspot.com/ • Alexey Shipilev— https://shipilev.net/ • concurrency-interest mailing list: http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
  • 105. Q & A