non-blocking michael-scott queue algorithm

105
Non-blocking Michael-Scott queue algorithm Alexey Fyodorov JUG.ru Group

Upload: alexey-fyodorov

Post on 22-Jan-2018

2.538 views

Category:

Engineering


1 download

TRANSCRIPT

Page 1: Non-blocking Michael-Scott queue algorithm

Non-blocking Michael-Scott queue algorithm

Alexey FyodorovJUG.ru Group

Page 2: Non-blocking Michael-Scott queue algorithm

• Programming

• Algorithms

• Concurrency

What is this talk about?

Page 3: Non-blocking Michael-Scott queue algorithm

• Programming

• Algorithms

• Concurrency

Areyousureyouneedit?

What is this talk about?

Page 4: Non-blocking Michael-Scott queue algorithm

For concurrency beginners

SorryPlease go to another room

Page 5: Non-blocking Michael-Scott queue algorithm

For concurrency beginners

SorryPlease go to another room

For non-blocking programming beginners

A short introduction

Page 6: Non-blocking Michael-Scott queue algorithm

For concurrency beginners

SorryPlease go to another room

For non-blocking programming beginners

A short introduction

For advanced concurrent programmers

CAS-based queue algorithm

Page 7: Non-blocking Michael-Scott queue algorithm

You have another room!

12:10Non-blocking Michael-Scott queue algorithm

Alexey Fyodorov

Easily scale enterprise applications

using distributed data gridsOndrej Mihaly

Page 8: Non-blocking Michael-Scott queue algorithm

Main Models

Shared Memory

write + read

Similar to how we program it

Concurrent Programming

Page 9: Non-blocking Michael-Scott queue algorithm

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

Page 10: Non-blocking Michael-Scott queue algorithm

Advantages of ParallelismResource utilization Utilization of several cores/CPUs

aka PERFORMANCE

Page 11: Non-blocking Michael-Scott queue algorithm

Advantages of ParallelismResource utilization

Simplicity Complexity goes to magic frameworks• ArrayBlockingQueue• ConcurrentHashMap• Akka

Utilization of several cores/CPUsaka PERFORMANCE

Page 12: Non-blocking Michael-Scott queue algorithm

Advantages of ParallelismResource utilization

Async handling

Simplicity

Utilization of several cores/CPUsaka PERFORMANCE

Complexity goes to magic frameworks• ArrayBlockingQueue• ConcurrentHashMap• Akka

Responsible services, Responsible UI

Page 13: Non-blocking Michael-Scott queue algorithm

Disadvantages of Locking

• Deadlocks

Page 14: Non-blocking Michael-Scott queue algorithm

Disadvantages of Locking

• Deadlocks

• Priority Inversion

Page 15: Non-blocking Michael-Scott queue algorithm

Disadvantages of Locking

• Deadlocks

• Priority Inversion

• Reliability• What will happen if lock owner die?

Page 16: Non-blocking Michael-Scott queue algorithm

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!

Page 17: Non-blocking Michael-Scott queue algorithm

Amdahl’s Law

α non-parallelizable part of the computation

1-α parallelizable part of the computation

p number of threads

Page 18: Non-blocking Michael-Scott queue algorithm

Amdahl’s Law

α non-parallelizable part of the computation

1-α parallelizable part of the computation

p number of threads

S = #

α$%&α'

Page 19: Non-blocking Michael-Scott queue algorithm

If-Modify-Write

volatile int value = 0;

Can we run it in multithreaded environment?

if (value == 0) {value = 42;

}

Page 20: Non-blocking Michael-Scott queue algorithm

If-Modify-Write

volatile int value = 0;

No atomicityif (value == 0) {

value = 42;}

}

Page 21: Non-blocking Michael-Scott queue algorithm

Compare-And-Set

int value = 0;

LOCKif (value == 0) {

value = 42;}

UNLOCK

Page 22: Non-blocking Michael-Scott queue algorithm

Introducing a Magic Operation

value.compareAndSet(0, 42);

int value = 0;

Page 23: Non-blocking Michael-Scott queue algorithm

Simulated CASlong 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);

}

Page 24: Non-blocking Michael-Scott queue algorithm

Simulated CASlong 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);

}

Page 25: Non-blocking Michael-Scott queue algorithm

Simulated CASlong 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);

}

Page 26: Non-blocking Michael-Scott queue algorithm

Simulated CASlong 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);

}

Page 27: Non-blocking Michael-Scott queue algorithm

Compare and Swap — Hardware Support

compare-and-swapCAS

load-link / store-conditionalLL/SC

cmpxchg ldrex/strex lwarx/stwcx

Page 28: Non-blocking Michael-Scott queue algorithm

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

Page 29: Non-blocking Michael-Scott queue algorithm

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

Page 30: Non-blocking Michael-Scott queue algorithm

Example. Atomic CounterAtomicLong value = new AtomicLong();

long get() {return value.get();

}

void increment() {long v;do {

v = value.get();} while (!value.compareAndSet(v, v + 1));

}

Page 31: Non-blocking Michael-Scott queue algorithm

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

Page 32: Non-blocking Michael-Scott queue algorithm

Atomics.Questions?

Page 33: Non-blocking Michael-Scott queue algorithm

Non-blocking Guarantees

Wait-Free Per-thread progress is guaranteed

Page 34: Non-blocking Michael-Scott queue algorithm

Non-blocking Guarantees

Wait-Free Per-thread progress is guaranteed

Lock-Free Overall progress is guaranteed

Page 35: Non-blocking Michael-Scott queue algorithm

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

Page 36: Non-blocking Michael-Scott queue algorithm

CAS-loopdo {

v = value.get();} while (!value.compareAndSet(v, v + 1));

A. Wait-FreeB. Lock-FreeC. Obstruction-Free

Page 37: Non-blocking Michael-Scott queue algorithm

CAS-loopdo {

v = value.get();} while (!value.compareAndSet(v, v + 1));

A. Wait-FreeB. Lock-FreeC. Obstruction-Free

*for modern hardware supporting CAS or LL/SC

Page 38: Non-blocking Michael-Scott queue algorithm

Stack & Concurrency

Page 39: Non-blocking Michael-Scott queue algorithm

class Node<E> {

final E item;

Node<E> next;

Node(E item) {this.item = item;

}

}

...

Page 40: Non-blocking Michael-Scott queue algorithm

class Node<E> {

final E item;

Node<E> next;

Node(E item) {this.item = item;

}

}

E3

E1

E2

Page 41: Non-blocking Michael-Scott queue algorithm

E3

E1

E2

top

Page 42: Non-blocking Michael-Scott queue algorithm

E3

E1

E2

top

item1

Thread 1

Page 43: Non-blocking Michael-Scott queue algorithm

E3

E1

E2

top

item1

Thread 1

Page 44: Non-blocking Michael-Scott queue algorithm

E3

E1

E2

top

item2item1

Thread 1 Thread 2

Page 45: Non-blocking Michael-Scott queue algorithm

E3

E1

E2

top

item2item1

Thread 1 Thread 2

Page 46: Non-blocking Michael-Scott queue algorithm

E3

E1

E2

item2item1

Thread 1 Thread 2top

Page 47: Non-blocking Michael-Scott queue algorithm

E3

E1

E2

item2item1

Thread 1 Thread 2

We need a synchronization

top

Page 48: Non-blocking Michael-Scott queue algorithm

Non-blocking Stack

Page 49: Non-blocking Michael-Scott queue algorithm

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

Page 50: Non-blocking Michael-Scott queue algorithm

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

Page 51: Non-blocking Michael-Scott queue algorithm

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

Page 52: Non-blocking Michael-Scott queue algorithm

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

Page 53: Non-blocking Michael-Scott queue algorithm

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

Page 54: Non-blocking Michael-Scott queue algorithm

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

Page 55: Non-blocking Michael-Scott queue algorithm

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

Page 56: Non-blocking Michael-Scott queue algorithm

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

Page 57: Non-blocking Michael-Scott queue algorithm

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

Page 58: Non-blocking Michael-Scott queue algorithm

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

Page 59: Non-blocking Michael-Scott queue algorithm

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

Page 60: Non-blocking Michael-Scott queue algorithm

Non-blocking Stack.Questions?

Page 61: Non-blocking Michael-Scott queue algorithm

Non-blocking Queue

Page 62: Non-blocking Michael-Scott queue algorithm

Michael and Scott, 1996https://www.research.ibm.com/people/m/michael/podc-1996.pdf

Threads help each other

Non-blocking queue

Page 63: Non-blocking Michael-Scott queue algorithm

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);

}

Page 64: Non-blocking Michael-Scott queue algorithm

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);

}

Page 65: Non-blocking Michael-Scott queue algorithm

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

Page 66: Non-blocking Michael-Scott queue algorithm

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

Page 67: Non-blocking Michael-Scott queue algorithm

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

Page 68: Non-blocking Michael-Scott queue algorithm

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

Page 69: Non-blocking Michael-Scott queue algorithm

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

Page 70: Non-blocking Michael-Scott queue algorithm

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

Page 71: Non-blocking Michael-Scott queue algorithm

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

Page 72: Non-blocking Michael-Scott queue algorithm

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

Page 73: Non-blocking Michael-Scott queue algorithm

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

Page 74: Non-blocking Michael-Scott queue algorithm

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

Page 75: Non-blocking Michael-Scott queue algorithm

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

Page 76: Non-blocking Michael-Scott queue algorithm

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

Page 77: Non-blocking Michael-Scott queue algorithm

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

Page 78: Non-blocking Michael-Scott queue algorithm

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

Page 79: Non-blocking Michael-Scott queue algorithm

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

Page 80: Non-blocking Michael-Scott queue algorithm

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

Page 81: Non-blocking Michael-Scott queue algorithm

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

Page 82: Non-blocking Michael-Scott queue algorithm

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

Page 83: Non-blocking Michael-Scott queue algorithm

Synchronization

Blocking

lock + unlock

Invariant: before & after

lock-based

Page 84: Non-blocking Michael-Scott queue algorithm

Synchronization

Blocking Non-blocking

lock + unlock CAS-loop

Invariant: before & after Semi-invariant

CAS-basedlock-based

Page 85: Non-blocking Michael-Scott queue algorithm

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;

}}

}}

}

Page 86: Non-blocking Michael-Scott queue algorithm

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;}

}}

}

Page 87: Non-blocking Michael-Scott queue algorithm

Non-blocking Queue in JDK

ConcurrentLinkedQueue is based on Michael-Scott queue

Page 88: Non-blocking Michael-Scott queue algorithm

� based on CAS-like operations

� use CAS-loop pattern

� threads help one another

Non-blocking algorithms. Summary

Page 89: Non-blocking Michael-Scott queue algorithm

Non-blocking Queue.Questions?

Page 90: Non-blocking Michael-Scott queue algorithm

ArrayBlockingQueue

Page 91: Non-blocking Michael-Scott queue algorithm

ArrayBlockingQueue

0 1 2 3 4 N-1...

Page 92: Non-blocking Michael-Scott queue algorithm

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()

Page 93: Non-blocking Michael-Scott queue algorithm

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()

Page 94: Non-blocking Michael-Scott queue algorithm

Modifications

Page 95: Non-blocking Michael-Scott queue algorithm

Ladan-Mozes, Shavit, 2004, 2008Key IDEA: use Doubly Linked List to avoid 2nd CAS

OptimisticApproach

http://people.csail.mit.edu/edya/publications/OptimisticFIFOQueue-journal.pdf

Page 96: Non-blocking Michael-Scott queue algorithm

Hoffman, Shalev, Shavit, 2007

BasketsQueue

http://people.csail.mit.edu/shanir/publications/Baskets%20Queue.pdf

Page 97: Non-blocking Michael-Scott queue algorithm

� Throughput is better

� no FIFO any more� usually you don’t need strong FIFO in real life

Baskets Queue

Page 98: Non-blocking Michael-Scott queue algorithm

Summary

Page 99: Non-blocking Michael-Scott queue algorithm

� Non-blocking algorithms are complicated� Blocking algorithms are easier

� correctness checking is difficult� difficult to support

� Sometimes it has better performance

Summary

Page 100: Non-blocking Michael-Scott queue algorithm

� Non-blocking algorithms are complicated� Blocking algorithms are easier

� correctness checking is difficult� difficult to support

� Sometimes it has better performance

Summary

Page 101: Non-blocking Michael-Scott queue algorithm

� 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

Page 102: Non-blocking Michael-Scott queue algorithm

Links & Books

Page 103: Non-blocking Michael-Scott queue algorithm

Books

Page 104: Non-blocking Michael-Scott queue algorithm

Links

• Nitsan Wakart — http://psy-lob-saw.blogspot.com/• AlexeyShipilev— https://shipilev.net/• concurrency-interestmailinglist:

http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest

Page 105: Non-blocking Michael-Scott queue algorithm

Q & A