SlideShare a Scribd company logo
Java Concurrency
Gotchas
Alex Miller
Questions to answer
• What are common concurrency problems?
• Why are they problems?
• How do I detect these problems?
• How to I correct these problems?
Areas of Focus
• Shared Data
• Coordination
• Performance
Areas of Focus
• Shared Data
• Coordination
• Performance

{

• Locking
• Visibility
• Atomicity
• Safe Publication
Unprotected Field
Access
A

What happens if we modify data
without locking?
Concurrency gotchas
Writer

Readers

Shared state
Locking
A
Shared Mutable Statics
public class MutableStatics {

FORMAT is mutable

private static final DateFormat FORMAT =
DateFormat.getDateInstance(DateFormat.MEDIUM);
public static Date parse(String str)
throws ParseException {
return FORMAT.parse(str);
}
...and this mutates it outside synchronization

}

public static void main(String arg[])
throws Exception {
MutableStatics.parse(“Jan 1, 2000”);
}
Shared mutable statics instance per call
public class MutableStatics {
public static Date parse(String str)
throws ParseException {
DateFormat format =
DateFormat.getDateInstance(DateFormat.MEDIUM);
return format.parse(str);
}

}

public static void main(String arg[])
throws Exception {
MutableStatics.parse(“Jan 1, 2000”);
}
Shared mutable statics ThreadLocal
public class MutableStatics {
private static final ThreadLocal<DateFormat> FORMAT
= new ThreadLocal<DateFormat>() {
@Override protected DateFormat initialValue() {
return DateFormat.getDateInstance(
DateFormat.MEDIUM);
}
};

}

public static Date parse(String str)
throws ParseException {
return FORMAT.get().parse(str);
}
Common JDK Examples
Danger!

Safe

• DateFormat
• Calendar
• Matcher

• Random
• Pattern
Synchronization
private int myField;
synchronized( What goes here? ) {
myField = 0;
}
DO NOT:
synchronize on null
MyObject obj = null;
synchronized( obj ) { NullPointerException!
// work
}
DO NOT:
change instance
MyObject obj = new MyObject();
synchronized( obj ) {
obj = new MyObject();
no longer synchronizing
on same object!

}
DO NOT:
synch on string literals
private static final String LOCK = “LOCK”;
synchronized( LOCK ) {
// work
What is the scope of LOCK?
}
DO NOT:
synch on autoboxed vals
private static final Integer LOCK = 0;
synchronized( LOCK ) { What is the scope of LOCK?
// work
}
DO NOT:
synch on ReentrantLock
Lock lock = new ReentrantLock();
synchronized(lock) {
// ...
Probably not what you meant here
}
Lock lock = new ReentrantLock();
lock.lock();
Probably more like this...
try {
// ...
} finally {
lock.unlock();
}
What should I lock on?
// The field you’re protecting
private final Map map = ...
synchronized(map) {
// ...access map
}

// Explicit lock object
private final Object lock = new Object();
synchronized(lock) {
// ...modify state
}
Visibility
Visibility problems
int x = 5;
Thread 1:
if(x == 5) {
x = 10;
}
Thread 2:
System.out.println(x);
Visibility problems
volatile int x = 5;
Thread 1:
if(x == 5) {
x = 10;
}
Thread 2:
System.out.println(x);
Inconsistent
Synchronization
public class SomeData {
private final Map data = new HashMap();
public void set(String key, String value) {
synchronized(data) {
Protecting writes
data.put(key, value);
}
}

}

public String get(String key) {
return data.get(key);
...but not reads
}
Double-checked locking
public class Singleton {
private static Singleton instance;

}

public static Singleton getInstance() {
Attempt to avoid synchronization
if(instance == null) {
synchronized(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
Double-checked locking
public class Singleton {
private static Singleton instance;

}

public static Singleton getInstance() {
if(instance == null) {
synchronized(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}

READ
READ
WRITE
Double-checked locking
- volatile
public class Singleton {
private static volatile Singleton instance;

}

public static Singleton getInstance() {
if(instance == null) {
synchronized(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
Double-checked locking
- initialize on demand
public class Singleton {
private static class SingletonHolder {
private static final Singleton instance
= new Singleton();
}

}

public static Singleton getInstance() {
return SingletonHolder.instance;
}
volatile arrays
public final class VolatileArray {
private volatile boolean[] vals;
public void flip(int i) {
Is the value of vals[i]
vals[i] = true;
visible to other threads?
}

}

public boolean flipped(int i) {
return vals[i];
}
Atomicity
Volatile counter
public class Counter {
private volatile int count;

}

public int next() {
return count++;
}

Looks atomic to me!
AtomicInteger counter
public class Counter {
private AtomicInteger count =
new AtomicInteger();

}

public int next() {
return count.getAndIncrement();
}
Really atomic via
encapsulation over
multiple actions
Composing atomic actions
public Object putIfAbsent(
Hashtable table, Object key, Object value) {
Hashtable is
thread-safe

if(table.containsKey(key)) {
// already present, return existing
table.get(key);
return null;

}

} else {
// doesn't exist, create new value
return table.put(key, value);
}

READ
READ
WRITE
Composing atomic actions
public Object putIfAbsent(
Hashtable table, Object key, Object value) {
Hashtable is
thread-safe

if(table.containsKey(key)) {
// already present, return existing
table.get(key);
return null;

}

} else {
// doesn't exist, create new value
return table.put(key, value);
}

READ
READ
WRITE
Participate in lock
public Object putIfAbsent(
Hashtable table, Object key, Object value) {
Hashtable is
thread-safe

}

synchronized(table) {
if(table.containsKey(key)) {
table.get(key);
return null;
} else {
return table.put(key, value);
}
}
Encapsulated compound
actions
public Object putIfAbsent(
ConcurrentHashMap table, Object key, Object value) {
}

return table.putIfAbsent(key, value);
Encpasulation FTW!
Assignment of
64 bit values
public class LongAssignment {
private long x;
public void setLong(long val) {
x = val;
Looks atomic to me,
}
but is it?

}
Assignment of
64 bit values - volatile
public class LongAssignment {
private volatile long x;
public void setLong(long val) {
x = val;
}
}
Safe publication
Listener in constructor
public interface DispatchListener {
void newFare(Customer customer);
}
public class Taxi
implements DispatchListener {
public Taxi(Dispatcher dispatcher) {
dispatcher.registerListener(this); We just published a
// other initialization
reference to this...oops!
}

}

public void newFare(Customer customer) {
// go to new customer’s location
}
Starting thread
in constructor
public class Cache {
private final Thread cleanerThread;
public Cache() {
cleanerThread = new Thread(new Cleaner(this));
cleanerThread.start();
this escapes again!
}

}

// Clean will call back to this method
public void cleanup() {
// clean up Cache
}
Static factory method
public class Cache {
// ...

}

public static Cache newCache() {
Cache cache = new Cache();
cache.startCleanerThread();
return cache;
}
Areas of Focus
• Shared Data
• Coordination
• Performance

{

• Threads
• Wait/notify
Threads
• THOU SHALT NOT:
• call Thread.stop()
• call Thread.suspend() or Thread.resume()

All monitors unlocked by ThreadDeath

Can lead to deadlock

• call Thread.destroy()
• call Thread.run()
• use ThreadGroups

Not implemented (or safe)

Wonʼt start Thread! Still in caller Thread.
Use a ThreadPoolExecutor instead.
wait/notify
// Thread 1
synchronized(lock) { You must synchronize.
while(! someCondition()) { Always wait in a loop.
lock.wait();
}
}
// Thread 2
synchronized(lock) { Synchronize here too!
satisfyCondition();
lock.notifyAll();
}
Condition is similar
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void waitTillChange() {
lock.lock();
try {
while(! someCondition()) condition.await();
} finally {
lock.unlock();
Condition is more
}
flexible than wait/notify.
}
public void change() {
lock.lock();
try {
satisfyCondition();
condition.signalAll();
} finally { lock.unlock(); } }
Areas of Focus
• Shared Data
• Coordination
• Performance

{

• Deadlock
• Spin wait
• Thread contention
Deadlock
// Thread 1
synchronized(lock1) {
synchronized(lock2) {
// stuff
}
}
// Thread 2
synchronized(lock2) {
synchronized(lock1) {
// stuff
}
}

Classic deadlock.
Deadlock avoidance
• Lock splitting
• Lock ordering
• Lock timeout
• tryLock
Spin wait
// Not efficient
private volatile boolean flag = false;
public void waitTillChange() {
while(! flag) {
Spin on flag, waiting for
Thread.sleep(100);
a change.
}
}
public void change() {
flag = true;
}
Replace with Condition
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private boolean flag = false;
public void waitTillChange() {
lock.lock();
try {
while(! flag) condition.await();
} finally {
lock.unlock();
}
}
public void change() {
lock.lock();
try {
flag = true;
condition.signalAll();
} finally { lock.unlock(); } }

Better but longer.
CountDownLatch
private final CountDownLatch latch =
new CountDownLatch(1);
public void waitTillChange() {
latch.await();
}
public void change() {
latch.countDown();
}

Coordination classes
like CountDownLatch
and CyclicBarrier cover
many common uses
better than Condition.
Lock contention
x

Hash f(x)

Bucket 0

Bucket 1

Bucket 2

Bucket 3
Lock striping
x

Hash g(x)

Hash f(x)

Bucket 0

Bucket 1

Hash f(x)

Bucket 0

Bucket 1
Final Exam
public class StatisticsImpl implements Statistics,
StatisticsImplementor {
private long queryExecutionCount;
public synchronized void queryExecuted(
String hql, int rows, long time) {
queryExecutionCount++;
// ... other stat collection
}
public long getQueryExecutionCount() {
return queryExecutionCount;
}

}

public synchronized void clear() {
queryExecutionCount = 0;
// ... clear all other stats
}
Final Exam
public class StatisticsImpl implements Statistics,
StatisticsImplementor {
private long queryExecutionCount;
Single shared lock for ALL stat values

public synchronized void queryExecuted(
String hql, int rows, long time) {
queryExecutionCount++;
// ... other stat collection
}
public long getQueryExecutionCount() {
return queryExecutionCount;
Read shared value
}

Non-atomic read
w/o synchronization of long value

}

public synchronized void clear() {
queryExecutionCount = 0;
Race condition if reading
// ... clear all other stats
stat and clearing
}
Thanks...
Twitter
Blog
Concurrency
links

http://twitter.com/puredanger
http://tech.puredanger.com
http://concurrency.tumblr.com

Refcard

http://refcardz.dzone.com/refcardz/
core-java-concurrency

Slides

http://slideshare.net/alexmiller

More Related Content

PPTX
PDF
Java Concurrency Idioms
PDF
Java synchronizers
PDF
Java Concurrency Gotchas
PPT
Java concurrency begining
DOCX
Java 5 concurrency
PDF
Circuit breaker
PPTX
#5 (Remote Method Invocation)
Java Concurrency Idioms
Java synchronizers
Java Concurrency Gotchas
Java concurrency begining
Java 5 concurrency
Circuit breaker
#5 (Remote Method Invocation)

What's hot (19)

PPT
04 Data Access
PDF
Sam wd programs
PPT
Refactoring Jdbc Programming
PDF
Ejb3 Dan Hinojosa
PDF
[Greach 17] make concurrency groovy again
ODP
Getting started with Clojure
PPTX
PDF
Lect04
PPT
Repetition is bad, repetition is bad.
PPT
2012 JDays Bad Tests Good Tests
PPTX
Java осень 2012 лекция 2
PPT
Xm lparsers
PDF
Java Programming - 08 java threading
PPTX
JDBC - JPA - Spring Data
PDF
IKH331-07-java-rmi
PDF
Actor Concurrency
PPT
Executing Sql Commands
PDF
4java Basic Syntax
PDF
Java OOP Programming language (Part 8) - Java Database JDBC
04 Data Access
Sam wd programs
Refactoring Jdbc Programming
Ejb3 Dan Hinojosa
[Greach 17] make concurrency groovy again
Getting started with Clojure
Lect04
Repetition is bad, repetition is bad.
2012 JDays Bad Tests Good Tests
Java осень 2012 лекция 2
Xm lparsers
Java Programming - 08 java threading
JDBC - JPA - Spring Data
IKH331-07-java-rmi
Actor Concurrency
Executing Sql Commands
4java Basic Syntax
Java OOP Programming language (Part 8) - Java Database JDBC
Ad

Viewers also liked (15)

PDF
Casco insurance claims handling, If P&C insurance case study
PPTX
Java7 Features
PDF
Psm 280 A Best Practices In Advancing Customer Marketing Innovations
PPT
Супермаркет услуг interinformer.com (для продавцов)
PPS
People Jam!
PPTX
Hippocrates 2.0
PPT
Systems Of The Body
PDF
Hol webinar summary
PDF
Elconceptodedisciplinaescolar.roberto l´hotelleríe
PDF
Debt Management, Collection on Ultimus BPM platform
PPT
Java basics
PDF
CASCO insurance claims handling
PPT
Medical Science Liaison Webinarv 2009
PPT
Sales Force Short Version
Casco insurance claims handling, If P&C insurance case study
Java7 Features
Psm 280 A Best Practices In Advancing Customer Marketing Innovations
Супермаркет услуг interinformer.com (для продавцов)
People Jam!
Hippocrates 2.0
Systems Of The Body
Hol webinar summary
Elconceptodedisciplinaescolar.roberto l´hotelleríe
Debt Management, Collection on Ultimus BPM platform
Java basics
CASCO insurance claims handling
Medical Science Liaison Webinarv 2009
Sales Force Short Version
Ad

Similar to Concurrency gotchas (20)

PDF
Java Concurrency Gotchas
PDF
Javaoneconcurrencygotchas 090610192215 Phpapp02
PPTX
Java concurrency
PDF
Java Concurrency by Example
PDF
Java Concurrency by Example
PPTX
Concurrency
ODP
Java Concurrency
PDF
Java Concurrency in Practice
PDF
Programming with Threads in Java
PPTX
Concurrency in Java
PPT
Hs java open_party
ODP
The free lunch is over
PDF
Study effective java item 78 synchronize access to mutable data
PDF
Practical Introduction to Java Memory Model
PDF
Concurrency Concepts in Java
PDF
Concurrency: Best Practices
PDF
jvm/java - towards lock-free concurrency
PPTX
Concurrency
PDF
Concurrency in Java
PDF
Concurrent Programming in Java
Java Concurrency Gotchas
Javaoneconcurrencygotchas 090610192215 Phpapp02
Java concurrency
Java Concurrency by Example
Java Concurrency by Example
Concurrency
Java Concurrency
Java Concurrency in Practice
Programming with Threads in Java
Concurrency in Java
Hs java open_party
The free lunch is over
Study effective java item 78 synchronize access to mutable data
Practical Introduction to Java Memory Model
Concurrency Concepts in Java
Concurrency: Best Practices
jvm/java - towards lock-free concurrency
Concurrency
Concurrency in Java
Concurrent Programming in Java

Recently uploaded (20)

PPTX
BOWEL ELIMINATION FACTORS AFFECTING AND TYPES
PDF
BÀI TẬP BỔ TRỢ 4 KỸ NĂNG TIẾNG ANH 9 GLOBAL SUCCESS - CẢ NĂM - BÁM SÁT FORM Đ...
PDF
RMMM.pdf make it easy to upload and study
PDF
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
PDF
O5-L3 Freight Transport Ops (International) V1.pdf
PPTX
Final Presentation General Medicine 03-08-2024.pptx
PDF
Insiders guide to clinical Medicine.pdf
PPTX
The Healthy Child – Unit II | Child Health Nursing I | B.Sc Nursing 5th Semester
PPTX
Cell Structure & Organelles in detailed.
PDF
Business Ethics Teaching Materials for college
PPTX
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
PDF
Module 4: Burden of Disease Tutorial Slides S2 2025
PDF
O7-L3 Supply Chain Operations - ICLT Program
PDF
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
PDF
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
PDF
Supply Chain Operations Speaking Notes -ICLT Program
PPTX
Pharmacology of Heart Failure /Pharmacotherapy of CHF
PPTX
master seminar digital applications in india
PPTX
human mycosis Human fungal infections are called human mycosis..pptx
PDF
FourierSeries-QuestionsWithAnswers(Part-A).pdf
BOWEL ELIMINATION FACTORS AFFECTING AND TYPES
BÀI TẬP BỔ TRỢ 4 KỸ NĂNG TIẾNG ANH 9 GLOBAL SUCCESS - CẢ NĂM - BÁM SÁT FORM Đ...
RMMM.pdf make it easy to upload and study
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
O5-L3 Freight Transport Ops (International) V1.pdf
Final Presentation General Medicine 03-08-2024.pptx
Insiders guide to clinical Medicine.pdf
The Healthy Child – Unit II | Child Health Nursing I | B.Sc Nursing 5th Semester
Cell Structure & Organelles in detailed.
Business Ethics Teaching Materials for college
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
Module 4: Burden of Disease Tutorial Slides S2 2025
O7-L3 Supply Chain Operations - ICLT Program
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
Supply Chain Operations Speaking Notes -ICLT Program
Pharmacology of Heart Failure /Pharmacotherapy of CHF
master seminar digital applications in india
human mycosis Human fungal infections are called human mycosis..pptx
FourierSeries-QuestionsWithAnswers(Part-A).pdf

Concurrency gotchas

  • 2. Questions to answer • What are common concurrency problems? • Why are they problems? • How do I detect these problems? • How to I correct these problems?
  • 3. Areas of Focus • Shared Data • Coordination • Performance
  • 4. Areas of Focus • Shared Data • Coordination • Performance { • Locking • Visibility • Atomicity • Safe Publication
  • 5. Unprotected Field Access A What happens if we modify data without locking?
  • 9. Shared Mutable Statics public class MutableStatics { FORMAT is mutable private static final DateFormat FORMAT = DateFormat.getDateInstance(DateFormat.MEDIUM); public static Date parse(String str) throws ParseException { return FORMAT.parse(str); } ...and this mutates it outside synchronization } public static void main(String arg[]) throws Exception { MutableStatics.parse(“Jan 1, 2000”); }
  • 10. Shared mutable statics instance per call public class MutableStatics { public static Date parse(String str) throws ParseException { DateFormat format = DateFormat.getDateInstance(DateFormat.MEDIUM); return format.parse(str); } } public static void main(String arg[]) throws Exception { MutableStatics.parse(“Jan 1, 2000”); }
  • 11. Shared mutable statics ThreadLocal public class MutableStatics { private static final ThreadLocal<DateFormat> FORMAT = new ThreadLocal<DateFormat>() { @Override protected DateFormat initialValue() { return DateFormat.getDateInstance( DateFormat.MEDIUM); } }; } public static Date parse(String str) throws ParseException { return FORMAT.get().parse(str); }
  • 12. Common JDK Examples Danger! Safe • DateFormat • Calendar • Matcher • Random • Pattern
  • 13. Synchronization private int myField; synchronized( What goes here? ) { myField = 0; }
  • 14. DO NOT: synchronize on null MyObject obj = null; synchronized( obj ) { NullPointerException! // work }
  • 15. DO NOT: change instance MyObject obj = new MyObject(); synchronized( obj ) { obj = new MyObject(); no longer synchronizing on same object! }
  • 16. DO NOT: synch on string literals private static final String LOCK = “LOCK”; synchronized( LOCK ) { // work What is the scope of LOCK? }
  • 17. DO NOT: synch on autoboxed vals private static final Integer LOCK = 0; synchronized( LOCK ) { What is the scope of LOCK? // work }
  • 18. DO NOT: synch on ReentrantLock Lock lock = new ReentrantLock(); synchronized(lock) { // ... Probably not what you meant here } Lock lock = new ReentrantLock(); lock.lock(); Probably more like this... try { // ... } finally { lock.unlock(); }
  • 19. What should I lock on? // The field you’re protecting private final Map map = ... synchronized(map) { // ...access map } // Explicit lock object private final Object lock = new Object(); synchronized(lock) { // ...modify state }
  • 21. Visibility problems int x = 5; Thread 1: if(x == 5) { x = 10; } Thread 2: System.out.println(x);
  • 22. Visibility problems volatile int x = 5; Thread 1: if(x == 5) { x = 10; } Thread 2: System.out.println(x);
  • 23. Inconsistent Synchronization public class SomeData { private final Map data = new HashMap(); public void set(String key, String value) { synchronized(data) { Protecting writes data.put(key, value); } } } public String get(String key) { return data.get(key); ...but not reads }
  • 24. Double-checked locking public class Singleton { private static Singleton instance; } public static Singleton getInstance() { Attempt to avoid synchronization if(instance == null) { synchronized(Singleton.class) { if(instance == null) { instance = new Singleton(); } } } return instance; }
  • 25. Double-checked locking public class Singleton { private static Singleton instance; } public static Singleton getInstance() { if(instance == null) { synchronized(Singleton.class) { if(instance == null) { instance = new Singleton(); } } } return instance; } READ READ WRITE
  • 26. Double-checked locking - volatile public class Singleton { private static volatile Singleton instance; } public static Singleton getInstance() { if(instance == null) { synchronized(Singleton.class) { if(instance == null) { instance = new Singleton(); } } } return instance; }
  • 27. Double-checked locking - initialize on demand public class Singleton { private static class SingletonHolder { private static final Singleton instance = new Singleton(); } } public static Singleton getInstance() { return SingletonHolder.instance; }
  • 28. volatile arrays public final class VolatileArray { private volatile boolean[] vals; public void flip(int i) { Is the value of vals[i] vals[i] = true; visible to other threads? } } public boolean flipped(int i) { return vals[i]; }
  • 30. Volatile counter public class Counter { private volatile int count; } public int next() { return count++; } Looks atomic to me!
  • 31. AtomicInteger counter public class Counter { private AtomicInteger count = new AtomicInteger(); } public int next() { return count.getAndIncrement(); } Really atomic via encapsulation over multiple actions
  • 32. Composing atomic actions public Object putIfAbsent( Hashtable table, Object key, Object value) { Hashtable is thread-safe if(table.containsKey(key)) { // already present, return existing table.get(key); return null; } } else { // doesn't exist, create new value return table.put(key, value); } READ READ WRITE
  • 33. Composing atomic actions public Object putIfAbsent( Hashtable table, Object key, Object value) { Hashtable is thread-safe if(table.containsKey(key)) { // already present, return existing table.get(key); return null; } } else { // doesn't exist, create new value return table.put(key, value); } READ READ WRITE
  • 34. Participate in lock public Object putIfAbsent( Hashtable table, Object key, Object value) { Hashtable is thread-safe } synchronized(table) { if(table.containsKey(key)) { table.get(key); return null; } else { return table.put(key, value); } }
  • 35. Encapsulated compound actions public Object putIfAbsent( ConcurrentHashMap table, Object key, Object value) { } return table.putIfAbsent(key, value); Encpasulation FTW!
  • 36. Assignment of 64 bit values public class LongAssignment { private long x; public void setLong(long val) { x = val; Looks atomic to me, } but is it? }
  • 37. Assignment of 64 bit values - volatile public class LongAssignment { private volatile long x; public void setLong(long val) { x = val; } }
  • 39. Listener in constructor public interface DispatchListener { void newFare(Customer customer); } public class Taxi implements DispatchListener { public Taxi(Dispatcher dispatcher) { dispatcher.registerListener(this); We just published a // other initialization reference to this...oops! } } public void newFare(Customer customer) { // go to new customer’s location }
  • 40. Starting thread in constructor public class Cache { private final Thread cleanerThread; public Cache() { cleanerThread = new Thread(new Cleaner(this)); cleanerThread.start(); this escapes again! } } // Clean will call back to this method public void cleanup() { // clean up Cache }
  • 41. Static factory method public class Cache { // ... } public static Cache newCache() { Cache cache = new Cache(); cache.startCleanerThread(); return cache; }
  • 42. Areas of Focus • Shared Data • Coordination • Performance { • Threads • Wait/notify
  • 44. • THOU SHALT NOT: • call Thread.stop() • call Thread.suspend() or Thread.resume() All monitors unlocked by ThreadDeath Can lead to deadlock • call Thread.destroy() • call Thread.run() • use ThreadGroups Not implemented (or safe) Wonʼt start Thread! Still in caller Thread. Use a ThreadPoolExecutor instead.
  • 45. wait/notify // Thread 1 synchronized(lock) { You must synchronize. while(! someCondition()) { Always wait in a loop. lock.wait(); } } // Thread 2 synchronized(lock) { Synchronize here too! satisfyCondition(); lock.notifyAll(); }
  • 46. Condition is similar private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); public void waitTillChange() { lock.lock(); try { while(! someCondition()) condition.await(); } finally { lock.unlock(); Condition is more } flexible than wait/notify. } public void change() { lock.lock(); try { satisfyCondition(); condition.signalAll(); } finally { lock.unlock(); } }
  • 47. Areas of Focus • Shared Data • Coordination • Performance { • Deadlock • Spin wait • Thread contention
  • 48. Deadlock // Thread 1 synchronized(lock1) { synchronized(lock2) { // stuff } } // Thread 2 synchronized(lock2) { synchronized(lock1) { // stuff } } Classic deadlock.
  • 49. Deadlock avoidance • Lock splitting • Lock ordering • Lock timeout • tryLock
  • 50. Spin wait // Not efficient private volatile boolean flag = false; public void waitTillChange() { while(! flag) { Spin on flag, waiting for Thread.sleep(100); a change. } } public void change() { flag = true; }
  • 51. Replace with Condition private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); private boolean flag = false; public void waitTillChange() { lock.lock(); try { while(! flag) condition.await(); } finally { lock.unlock(); } } public void change() { lock.lock(); try { flag = true; condition.signalAll(); } finally { lock.unlock(); } } Better but longer.
  • 52. CountDownLatch private final CountDownLatch latch = new CountDownLatch(1); public void waitTillChange() { latch.await(); } public void change() { latch.countDown(); } Coordination classes like CountDownLatch and CyclicBarrier cover many common uses better than Condition.
  • 53. Lock contention x Hash f(x) Bucket 0 Bucket 1 Bucket 2 Bucket 3
  • 54. Lock striping x Hash g(x) Hash f(x) Bucket 0 Bucket 1 Hash f(x) Bucket 0 Bucket 1
  • 55. Final Exam public class StatisticsImpl implements Statistics, StatisticsImplementor { private long queryExecutionCount; public synchronized void queryExecuted( String hql, int rows, long time) { queryExecutionCount++; // ... other stat collection } public long getQueryExecutionCount() { return queryExecutionCount; } } public synchronized void clear() { queryExecutionCount = 0; // ... clear all other stats }
  • 56. Final Exam public class StatisticsImpl implements Statistics, StatisticsImplementor { private long queryExecutionCount; Single shared lock for ALL stat values public synchronized void queryExecuted( String hql, int rows, long time) { queryExecutionCount++; // ... other stat collection } public long getQueryExecutionCount() { return queryExecutionCount; Read shared value } Non-atomic read w/o synchronization of long value } public synchronized void clear() { queryExecutionCount = 0; Race condition if reading // ... clear all other stats stat and clearing }