SlideShare a Scribd company logo
1 of 25
Download to read offline
Wait for your fortune
without blocking!
© Roman Elizarov, Devexperts, 2016
Why concurrency?
• Key motivators
- Performance
- Scalability
• Unless you need both, don’t
bother with concurrency:
- Write single-threaded
- Scale by running multiple
copies of code
Thread 1
Thread 2
Thread N
Shared
Object
Practical examples:
queue, cache,
dictionary, state,
statistics, log, etc
Share nothing and
sleep well
What is blocking?
What is non-blocking algorithm?
Blocking (aka locking)
• Semi-formally
• In Java practice non-blocking algorithms
- just read/write volatile variable and/or use
- j.u.c.a.AtomicXXX classes with compareAndSet and other methods
• Blocking algorithms (with locks) use
- synchronized (…) which produces monitorEnter/monitorExit instrs
- j.u.c.l.Lock lock/unlock methods
- NOTE: You can code blocking without realizing it
An algorithm is called non-blocking (lock-free)
if suspension of any thread cannot
cause suspension of another thread
Toy problem solved with locks
Locks are the easiest way to
make your object linearizable
(aka thread-safe)
Just protect all operations on
a shared state with the same
lock (or monitor)
1
2
3
What is waiting [for condition]?
What is waiting operation?
sometimes aka “blocking”, too 
Waiting for condition
• Formally
• For example, let’s implement partial takeValue operation that is
defined only when there is value != null in DataHolder
• Waiting is orthogonal to blocking/non-blocking
Partial function
from object state set X to result set Y
is defined only on a subset of X’ of X.
Method invocation can complete only
when object state is in X’
(when condition is satisfied).
Waiting is easy with monitors
1
2
If in doubt, always use notifyAll instead
of notify (but can use notify here)
This is code with locks (synchronized):
suspension of one thread on any of these
lines causes suspension of all other
threads that attempt to do any operation
This is waiting code (partial function):
it is only defined when value != null
Why go non-blocking (aka lock-free)?
• Performance
- Locking is expensive when contended
- Actually, context switches are expensive
• Dead-lock avoidance
- Too much locking can get you into trouble
- Sometimes it is just easier to get rid of locks
Let’s go lock-free
1
2
3
4
Lock-free partial operations (waiting aka parking)
2
3
4
1
Lock-free wakeup (aka unparking)
• Note: in lock-free code order is important (first update, then unpark)
• Updaters are 100% wait-free (never locked out by other threads)
• Taker (takeValue) can get starved in CAS loop, but still non-
blocking (formally, lock-free)
Park/unpark magic
LockSupport.unpark(T): “Makes available
the permit for the given thread, if it was not
already available. If the thread was blocked
on park then it will unblock. Otherwise, its
next call to park is guaranteed not to block.”
U update state unpark(T)
updateValue
T check state park()
takeValue
^ value == null
Lock-free waiting from different/multiple threads
• Must maintain wait queue of threads in a lock-free way
- This is a non-trivial
• j.u.c.l.AbstractQueuedSynchronizer is a good place to start
• It is used to implement a number of j.u.c.* classes:
- ReentrantLock
- ReentrantReadWriteLock
- Semaphore
- CountDownLatch
• You can use it to for your own needs, too
Anatomy of AbstractQueuedSynchronizer
int state; // optionally use for state
wait queue <Node>; // nodes reference threads
int getState()
void setState(int newState)
boolean compareAndSetState(int expect, int update)
boolean tryAcquire(int arg)
boolean tryRelease(int arg)
int tryAcquireShared(int arg)
boolean tryReleaseShared(int arg)
void acquire(int arg)
void acquireInterruptibly(int arg)
boolean tryAcquireNanos(int arg, long nanos)
boolean release(int arg)
void acquireShared(int arg)
// and others
1
private state
2
state access
3
override
4
use
almost
separate
aspects
Anatomy of AbstractQueuedSynchronizer (2)
1
3
2
adds to
wait queue
4
unlinks from
wait queue
Our own synchronizer
1
2
3
Use synchronizer to implement notify/wait
1
2
3
Why double check? (more internals)
void doAcquireXXX(int arg) {
addToWaitQueue();
for (;;) {
if (isFirstInQueue() && tryAcquire(arg)) {
unlinkFromWaitQueue(); return;
}
doPark();
}
}
U update state release -> unparkSuccessor()
updateValue
T tryAcquire unlinkFromWaitQueue()
takeValue
^ CAS(value, oldValue, null)
Simplified code
Naïve “performance improvement”
• The idea is to unpark just one thread when setting value for the first
time only (and avoid unparking on subsequent updates)
• DOES NOT WORK SUBTLY: updateValue may cause concurrent
tryAcquire to fail on CAS and park, but we don’t call release in this
case anymore, so it will never unpark
.
1
2
Corrected Sync.tryAcquire method
• Use CAS-loop idiom to retry in the case of contention
• Optimal version in terms of context switching
1
2
This is optimal, but not fair!
• Let’s take a closer look at AQS.acquireXXX
• Thread might jump ahead of the queue
- Good or bad? – depends on the problem being solved
Make it fair (if needed)
Conclusion
• Waiting can be implemented in a non-blocking way
- Recap non-blocking: suspension of any thread (on any line of code)
cannot cause suspension of another thread
- Bonus: context switch only when really need to wait & wakeup
- Fairness: is an optional aspect of waiting
• AbstractQueuedSynchronizer
- is designed for writing custom lock-like classes
- but can be repurposed as a ready wait-queue impl for other cases
Lock-free programming is
extremely bug-prone
Thank you
Slides are available at elizarov.livejournal.com
Twitter at @relizarov

More Related Content

What's hot

JVM for Dummies - OSCON 2011
JVM for Dummies - OSCON 2011JVM for Dummies - OSCON 2011
JVM for Dummies - OSCON 2011
Charles Nutter
 

What's hot (20)

Java Concurrency, Memory Model, and Trends
Java Concurrency, Memory Model, and TrendsJava Concurrency, Memory Model, and Trends
Java Concurrency, Memory Model, and Trends
 
Effective java - concurrency
Effective java - concurrencyEffective java - concurrency
Effective java - concurrency
 
Modern Java Workshop
Modern Java WorkshopModern Java Workshop
Modern Java Workshop
 
Java Concurrency Gotchas
Java Concurrency GotchasJava Concurrency Gotchas
Java Concurrency Gotchas
 
Clojure, Plain and Simple
Clojure, Plain and SimpleClojure, Plain and Simple
Clojure, Plain and Simple
 
Async programming and python
Async programming and pythonAsync programming and python
Async programming and python
 
Working With Concurrency In Java 8
Working With Concurrency In Java 8Working With Concurrency In Java 8
Working With Concurrency In Java 8
 
Java Concurrency in Practice
Java Concurrency in PracticeJava Concurrency in Practice
Java Concurrency in Practice
 
JavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesJavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for Dummies
 
Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John Stevenson
 
Modern Java Concurrency
Modern Java ConcurrencyModern Java Concurrency
Modern Java Concurrency
 
Fast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaFast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible Java
 
JVM for Dummies - OSCON 2011
JVM for Dummies - OSCON 2011JVM for Dummies - OSCON 2011
JVM for Dummies - OSCON 2011
 
Concurrency Programming in Java - 07 - High-level Concurrency objects, Lock O...
Concurrency Programming in Java - 07 - High-level Concurrency objects, Lock O...Concurrency Programming in Java - 07 - High-level Concurrency objects, Lock O...
Concurrency Programming in Java - 07 - High-level Concurrency objects, Lock O...
 
Concurrency with java
Concurrency with javaConcurrency with java
Concurrency with java
 
Java 10, Java 11 and beyond
Java 10, Java 11 and beyondJava 10, Java 11 and beyond
Java 10, Java 11 and beyond
 
[Java concurrency]01.thread management
[Java concurrency]01.thread management[Java concurrency]01.thread management
[Java concurrency]01.thread management
 
Concurrency in Java
Concurrency in  JavaConcurrency in  Java
Concurrency in Java
 
Clojure for Java developers
Clojure for Java developersClojure for Java developers
Clojure for Java developers
 
Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013Beyond JVM - YOW! Sydney 2013
Beyond JVM - YOW! Sydney 2013
 

Similar to Wait for your fortune without Blocking!

Medical Image Processing Strategies for multi-core CPUs
Medical Image Processing Strategies for multi-core CPUsMedical Image Processing Strategies for multi-core CPUs
Medical Image Processing Strategies for multi-core CPUs
Daniel Blezek
 
CS844 U1 Individual Project
CS844 U1 Individual ProjectCS844 U1 Individual Project
CS844 U1 Individual Project
ThienSi Le
 
Programming with Threads in Java
Programming with Threads in JavaProgramming with Threads in Java
Programming with Threads in Java
koji lin
 
AOS Lab 4: If you liked it, then you should have put a “lock” on it
AOS Lab 4: If you liked it, then you should have put a “lock” on itAOS Lab 4: If you liked it, then you should have put a “lock” on it
AOS Lab 4: If you liked it, then you should have put a “lock” on it
Zubair Nabi
 
Linux synchronization tools
Linux synchronization toolsLinux synchronization tools
Linux synchronization tools
mukul bhardwaj
 

Similar to Wait for your fortune without Blocking! (20)

Adv java unit 1 M.Sc CS.pdf
Adv java unit 1 M.Sc CS.pdfAdv java unit 1 M.Sc CS.pdf
Adv java unit 1 M.Sc CS.pdf
 
Java Course 10: Threads and Concurrency
Java Course 10: Threads and ConcurrencyJava Course 10: Threads and Concurrency
Java Course 10: Threads and Concurrency
 
Synchronization problem with threads
Synchronization problem with threadsSynchronization problem with threads
Synchronization problem with threads
 
Java Thread
Java ThreadJava Thread
Java Thread
 
Medical Image Processing Strategies for multi-core CPUs
Medical Image Processing Strategies for multi-core CPUsMedical Image Processing Strategies for multi-core CPUs
Medical Image Processing Strategies for multi-core CPUs
 
CS844 U1 Individual Project
CS844 U1 Individual ProjectCS844 U1 Individual Project
CS844 U1 Individual Project
 
Let's Talk Locks!
Let's Talk Locks!Let's Talk Locks!
Let's Talk Locks!
 
Storm Real Time Computation
Storm Real Time ComputationStorm Real Time Computation
Storm Real Time Computation
 
Programming with Threads in Java
Programming with Threads in JavaProgramming with Threads in Java
Programming with Threads in Java
 
AOS Lab 4: If you liked it, then you should have put a “lock” on it
AOS Lab 4: If you liked it, then you should have put a “lock” on itAOS Lab 4: If you liked it, then you should have put a “lock” on it
AOS Lab 4: If you liked it, then you should have put a “lock” on it
 
Towards a Scalable Non-Blocking Coding Style
Towards a Scalable Non-Blocking Coding StyleTowards a Scalable Non-Blocking Coding Style
Towards a Scalable Non-Blocking Coding Style
 
Multithreading Presentation
Multithreading PresentationMultithreading Presentation
Multithreading Presentation
 
Linux synchronization tools
Linux synchronization toolsLinux synchronization tools
Linux synchronization tools
 
.NET Multithreading/Multitasking
.NET Multithreading/Multitasking.NET Multithreading/Multitasking
.NET Multithreading/Multitasking
 
1.17 Thread in java.pptx
1.17 Thread in java.pptx1.17 Thread in java.pptx
1.17 Thread in java.pptx
 
java_threads.ppt
java_threads.pptjava_threads.ppt
java_threads.ppt
 
Here comes the Loom - Ya!vaConf.pdf
Here comes the Loom - Ya!vaConf.pdfHere comes the Loom - Ya!vaConf.pdf
Here comes the Loom - Ya!vaConf.pdf
 
Concurrency
ConcurrencyConcurrency
Concurrency
 
Threading in java - a pragmatic primer
Threading in java - a pragmatic primerThreading in java - a pragmatic primer
Threading in java - a pragmatic primer
 
Groovy concurrency
Groovy concurrencyGroovy concurrency
Groovy concurrency
 

More from Roman Elizarov

Многопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и ПрактикаМногопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и Практика
Roman Elizarov
 
Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)
Roman Elizarov
 
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Roman Elizarov
 
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
Roman Elizarov
 
Millions quotes per second in pure java
Millions quotes per second in pure javaMillions quotes per second in pure java
Millions quotes per second in pure java
Roman Elizarov
 
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
Roman Elizarov
 
The theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmerThe theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmer
Roman Elizarov
 

More from Roman Elizarov (19)

Kotlin Coroutines in Practice @ KotlinConf 2018
Kotlin Coroutines in Practice @ KotlinConf 2018Kotlin Coroutines in Practice @ KotlinConf 2018
Kotlin Coroutines in Practice @ KotlinConf 2018
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
 
Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017
 
Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017
 
Scale Up with Lock-Free Algorithms @ JavaOne
Scale Up with Lock-Free Algorithms @ JavaOneScale Up with Lock-Free Algorithms @ JavaOne
Scale Up with Lock-Free Algorithms @ JavaOne
 
Kotlin Coroutines Reloaded
Kotlin Coroutines ReloadedKotlin Coroutines Reloaded
Kotlin Coroutines Reloaded
 
Lock-free algorithms for Kotlin Coroutines
Lock-free algorithms for Kotlin CoroutinesLock-free algorithms for Kotlin Coroutines
Lock-free algorithms for Kotlin Coroutines
 
Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutines
 
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2016 NEERC (Northeastern European Regional Contest) Problems Review
 
Многопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и ПрактикаМногопоточное Программирование - Теория и Практика
Многопоточное Программирование - Теория и Практика
 
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2015 NEERC (Northeastern European Regional Contest) Problems Review
 
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2014 NEERC (Northeastern European Regional Contest) Problems Review
 
Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)Многопоточные Алгоритмы (для BitByte 2014)
Многопоточные Алгоритмы (для BitByte 2014)
 
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
Теоретический минимум для понимания Java Memory Model (для JPoint 2014)
 
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2013 NEERC (Northeastern European Regional Contest) Problems Review
 
Millions quotes per second in pure java
Millions quotes per second in pure javaMillions quotes per second in pure java
Millions quotes per second in pure java
 
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems ReviewACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
ACM ICPC 2012 NEERC (Northeastern European Regional Contest) Problems Review
 
The theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmerThe theory of concurrent programming for a seasoned programmer
The theory of concurrent programming for a seasoned programmer
 
Пишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данныхПишем самый быстрый хеш для кэширования данных
Пишем самый быстрый хеш для кэширования данных
 

Recently uploaded

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Recently uploaded (20)

AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 

Wait for your fortune without Blocking!

  • 1. Wait for your fortune without blocking! © Roman Elizarov, Devexperts, 2016
  • 2. Why concurrency? • Key motivators - Performance - Scalability • Unless you need both, don’t bother with concurrency: - Write single-threaded - Scale by running multiple copies of code Thread 1 Thread 2 Thread N Shared Object Practical examples: queue, cache, dictionary, state, statistics, log, etc Share nothing and sleep well
  • 3. What is blocking? What is non-blocking algorithm?
  • 4. Blocking (aka locking) • Semi-formally • In Java practice non-blocking algorithms - just read/write volatile variable and/or use - j.u.c.a.AtomicXXX classes with compareAndSet and other methods • Blocking algorithms (with locks) use - synchronized (…) which produces monitorEnter/monitorExit instrs - j.u.c.l.Lock lock/unlock methods - NOTE: You can code blocking without realizing it An algorithm is called non-blocking (lock-free) if suspension of any thread cannot cause suspension of another thread
  • 5. Toy problem solved with locks Locks are the easiest way to make your object linearizable (aka thread-safe) Just protect all operations on a shared state with the same lock (or monitor) 1 2 3
  • 6. What is waiting [for condition]? What is waiting operation? sometimes aka “blocking”, too 
  • 7. Waiting for condition • Formally • For example, let’s implement partial takeValue operation that is defined only when there is value != null in DataHolder • Waiting is orthogonal to blocking/non-blocking Partial function from object state set X to result set Y is defined only on a subset of X’ of X. Method invocation can complete only when object state is in X’ (when condition is satisfied).
  • 8. Waiting is easy with monitors 1 2 If in doubt, always use notifyAll instead of notify (but can use notify here) This is code with locks (synchronized): suspension of one thread on any of these lines causes suspension of all other threads that attempt to do any operation This is waiting code (partial function): it is only defined when value != null
  • 9. Why go non-blocking (aka lock-free)? • Performance - Locking is expensive when contended - Actually, context switches are expensive • Dead-lock avoidance - Too much locking can get you into trouble - Sometimes it is just easier to get rid of locks
  • 11. Lock-free partial operations (waiting aka parking) 2 3 4 1
  • 12. Lock-free wakeup (aka unparking) • Note: in lock-free code order is important (first update, then unpark) • Updaters are 100% wait-free (never locked out by other threads) • Taker (takeValue) can get starved in CAS loop, but still non- blocking (formally, lock-free)
  • 13. Park/unpark magic LockSupport.unpark(T): “Makes available the permit for the given thread, if it was not already available. If the thread was blocked on park then it will unblock. Otherwise, its next call to park is guaranteed not to block.” U update state unpark(T) updateValue T check state park() takeValue ^ value == null
  • 14. Lock-free waiting from different/multiple threads • Must maintain wait queue of threads in a lock-free way - This is a non-trivial • j.u.c.l.AbstractQueuedSynchronizer is a good place to start • It is used to implement a number of j.u.c.* classes: - ReentrantLock - ReentrantReadWriteLock - Semaphore - CountDownLatch • You can use it to for your own needs, too
  • 15. Anatomy of AbstractQueuedSynchronizer int state; // optionally use for state wait queue <Node>; // nodes reference threads int getState() void setState(int newState) boolean compareAndSetState(int expect, int update) boolean tryAcquire(int arg) boolean tryRelease(int arg) int tryAcquireShared(int arg) boolean tryReleaseShared(int arg) void acquire(int arg) void acquireInterruptibly(int arg) boolean tryAcquireNanos(int arg, long nanos) boolean release(int arg) void acquireShared(int arg) // and others 1 private state 2 state access 3 override 4 use almost separate aspects
  • 16. Anatomy of AbstractQueuedSynchronizer (2) 1 3 2 adds to wait queue 4 unlinks from wait queue
  • 18. Use synchronizer to implement notify/wait 1 2 3
  • 19. Why double check? (more internals) void doAcquireXXX(int arg) { addToWaitQueue(); for (;;) { if (isFirstInQueue() && tryAcquire(arg)) { unlinkFromWaitQueue(); return; } doPark(); } } U update state release -> unparkSuccessor() updateValue T tryAcquire unlinkFromWaitQueue() takeValue ^ CAS(value, oldValue, null) Simplified code
  • 20. Naïve “performance improvement” • The idea is to unpark just one thread when setting value for the first time only (and avoid unparking on subsequent updates) • DOES NOT WORK SUBTLY: updateValue may cause concurrent tryAcquire to fail on CAS and park, but we don’t call release in this case anymore, so it will never unpark . 1 2
  • 21. Corrected Sync.tryAcquire method • Use CAS-loop idiom to retry in the case of contention • Optimal version in terms of context switching 1 2
  • 22. This is optimal, but not fair! • Let’s take a closer look at AQS.acquireXXX • Thread might jump ahead of the queue - Good or bad? – depends on the problem being solved
  • 23. Make it fair (if needed)
  • 24. Conclusion • Waiting can be implemented in a non-blocking way - Recap non-blocking: suspension of any thread (on any line of code) cannot cause suspension of another thread - Bonus: context switch only when really need to wait & wakeup - Fairness: is an optional aspect of waiting • AbstractQueuedSynchronizer - is designed for writing custom lock-like classes - but can be repurposed as a ready wait-queue impl for other cases Lock-free programming is extremely bug-prone
  • 25. Thank you Slides are available at elizarov.livejournal.com Twitter at @relizarov