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


                 {
                     • Locking
• Shared Data        • Visibility
                     • Atomicity
• Coordination
                     • Safe Publication
• Performance
Unprotected Field
     Access

              A



What happens if we modify data
      without locking?
Java 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   • Random
• Calendar     • Pattern
• Matcher
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() {
      if(instance == null) {     Attempt to avoid synchronization
        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) {                  READ
        synchronized(Singleton.class) {
          if(instance == null) {              READ
            instance = new Singleton();       WRITE
          }
        }
      }
      return instance;
    }
}
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)) {                 READ
      // already present, return existing
      table.get(key);                            READ
      return null;

    } else {
      // doesn't exist, create new value         WRITE
      return table.put(key, value);
    }
}
Composing atomic actions
public Object putIfAbsent(
  Hashtable table, Object key, Object value) {
         Hashtable is
         thread-safe

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

    } else {
      // doesn't exist, create new value         WRITE
      return table.put(key, value);
    }
}
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() All monitors unlocked by ThreadDeath


 • call Thread.suspend() or Thread.resume()
                                      Can lead to deadlock



 • call Thread.destroy()     Not implemented (or safe)


 • call Thread.run()   Wonʼt start Thread! Still in caller Thread.


 • use ThreadGroups        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       • Deadlock
• Performance    {   • Spin wait
                     • Thread contention
Deadlock
// Thread 1
synchronized(lock1) {
  synchronized(lock2) {
    // stuff
  }
}
                          Classic deadlock.
// Thread 2
synchronized(lock2) {
  synchronized(lock1) {
    // stuff
  }
}
Deadlock avoidance

• Lock splitting
• Lock ordering
• Lock timeout
• tryLock
Spin wait
// Not efficient
private volatile boolean flag = false;

public void waitTillChange() {
  while(! flag) {
    Thread.sleep(100);      Spin on flag, waiting for
                            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();                     Better but longer.
  }
}
public void change() {
  lock.lock();
  try {
    flag = true;
    condition.signalAll();
  } finally { lock.unlock(); } }
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)                                 Hash f(x)




Bucket 0           Bucket 1               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       http://twitter.com/puredanger
Blog          http://tech.puredanger.com
Concurrency   http://concurrency.tumblr.com
links
              http://refcardz.dzone.com/refcardz/
Refcard
              core-java-concurrency
Slides        http://slideshare.net/alexmiller

More Related Content

PDF
From Java 11 to 17 and beyond.pdf
PPTX
Exceptions in Java
PDF
Angular and The Case for RxJS
PDF
Drools Introduction
PDF
07 java collection
PDF
Java 8 features
PPTX
Exception handling
PPTX
Component lifecycle hooks in Angular 2.0
From Java 11 to 17 and beyond.pdf
Exceptions in Java
Angular and The Case for RxJS
Drools Introduction
07 java collection
Java 8 features
Exception handling
Component lifecycle hooks in Angular 2.0

What's hot (20)

PPTX
Spring boot Introduction
PPT
Advanced JavaScript
PDF
Fun with click house window functions webinar slides 2021-08-19
PDF
jQuery Effects
PPTX
PPTX
Exception Handling in Java
PPT
Exception Handling in JAVA
PDF
An introduction to Rust: the modern programming language to develop safe and ...
PPT
Control statements in java programmng
PPTX
Spring Boot
PDF
Rules to Hack By - Offensivecon 2022 keynote
PDF
Go Concurrency
PDF
Collections In Java
PPT
Spring mvc
PPTX
Introduction to kotlin
PPT
JUnit 4
PPTX
Functional programming with Java 8
PPTX
Spring Security 5
PPT
Swing and AWT in java
PPTX
Android Intent.pptx
Spring boot Introduction
Advanced JavaScript
Fun with click house window functions webinar slides 2021-08-19
jQuery Effects
Exception Handling in Java
Exception Handling in JAVA
An introduction to Rust: the modern programming language to develop safe and ...
Control statements in java programmng
Spring Boot
Rules to Hack By - Offensivecon 2022 keynote
Go Concurrency
Collections In Java
Spring mvc
Introduction to kotlin
JUnit 4
Functional programming with Java 8
Spring Security 5
Swing and AWT in java
Android Intent.pptx
Ad

Viewers also liked (20)

PPTX
Effective java - concurrency
PDF
Dzone core java concurrency -_
PDF
[Java concurrency]01.thread management
PDF
Blogging ZOMG
PDF
Caching In The Cloud
PDF
Innovative Software
PDF
Releasing Relational Data to the Semantic Web
PDF
Scaling Your Cache
PDF
Cold Hard Cache
PDF
Stream Execution with Clojure and Fork/join
PDF
Project Fortress
PDF
Groovy concurrency
PDF
Scaling Hibernate with Terracotta
PDF
Working With Concurrency In Java 8
PDF
Java Concurrency in Practice
ODP
Java Concurrency, Memory Model, and Trends
PDF
Cracking clojure
PDF
Clojure: The Art of Abstraction
KEY
Modern Java Concurrency
PDF
Lessons from the intelligent investor
Effective java - concurrency
Dzone core java concurrency -_
[Java concurrency]01.thread management
Blogging ZOMG
Caching In The Cloud
Innovative Software
Releasing Relational Data to the Semantic Web
Scaling Your Cache
Cold Hard Cache
Stream Execution with Clojure and Fork/join
Project Fortress
Groovy concurrency
Scaling Hibernate with Terracotta
Working With Concurrency In Java 8
Java Concurrency in Practice
Java Concurrency, Memory Model, and Trends
Cracking clojure
Clojure: The Art of Abstraction
Modern Java Concurrency
Lessons from the intelligent investor
Ad

Similar to Java Concurrency Gotchas (20)

PDF
Java Concurrency Gotchas
PDF
Javaoneconcurrencygotchas 090610192215 Phpapp02
PDF
Concurrency gotchas
KEY
第1回 チキチキ『( ゜ェ゜)・;'.、ゴフッ』 - シングルトンパターン(Java)
PDF
.NET Multithreading and File I/O
PDF
From Runnable and synchronized To atomically() and parallel()
PPTX
Java concurrency
PDF
3. Объекты, классы и пакеты в Java
PPTX
Use of Apache Commons and Utilities
DOCX
Java 5 concurrency
PDF
Scala in practice
ODP
AST Transformations at JFokus
PPTX
Java осень 2012 лекция 2
ODP
Ast transformations
PPT
Thread
PPT
04 threads
PDF
A linked stack is implemented using a standard Node class as follows.pdf
PPT
Java concurrency begining
PPTX
What’s new in C# 6
PDF
using the code below create a method called getCollisionCount that w.pdf
Java Concurrency Gotchas
Javaoneconcurrencygotchas 090610192215 Phpapp02
Concurrency gotchas
第1回 チキチキ『( ゜ェ゜)・;'.、ゴフッ』 - シングルトンパターン(Java)
.NET Multithreading and File I/O
From Runnable and synchronized To atomically() and parallel()
Java concurrency
3. Объекты, классы и пакеты в Java
Use of Apache Commons and Utilities
Java 5 concurrency
Scala in practice
AST Transformations at JFokus
Java осень 2012 лекция 2
Ast transformations
Thread
04 threads
A linked stack is implemented using a standard Node class as follows.pdf
Java concurrency begining
What’s new in C# 6
using the code below create a method called getCollisionCount that w.pdf

More from Alex Miller (12)

PDF
Clojure/West Overview (12/1/11)
PDF
Concurrent Stream Processing
PDF
Tree Editing with Zippers
PDF
Scaling Your Cache And Caching At Scale
PDF
Marshmallow Test
PDF
Strange Loop Conference 2009
PDF
Java Collections API
PDF
Java Concurrency Idioms
PDF
Design Patterns Reconsidered
PDF
Java 7 Preview
PDF
Exploring Terracotta
PDF
Actor Concurrency
Clojure/West Overview (12/1/11)
Concurrent Stream Processing
Tree Editing with Zippers
Scaling Your Cache And Caching At Scale
Marshmallow Test
Strange Loop Conference 2009
Java Collections API
Java Concurrency Idioms
Design Patterns Reconsidered
Java 7 Preview
Exploring Terracotta
Actor Concurrency

Recently uploaded (20)

PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
Machine Learning_overview_presentation.pptx
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPTX
A Presentation on Artificial Intelligence
PDF
Approach and Philosophy of On baking technology
PPTX
sap open course for s4hana steps from ECC to s4
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPTX
Cloud computing and distributed systems.
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PPTX
Spectroscopy.pptx food analysis technology
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
Big Data Technologies - Introduction.pptx
Dropbox Q2 2025 Financial Results & Investor Presentation
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
“AI and Expert System Decision Support & Business Intelligence Systems”
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Spectral efficient network and resource selection model in 5G networks
Machine Learning_overview_presentation.pptx
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Chapter 3 Spatial Domain Image Processing.pdf
A Presentation on Artificial Intelligence
Approach and Philosophy of On baking technology
sap open course for s4hana steps from ECC to s4
Digital-Transformation-Roadmap-for-Companies.pptx
Advanced methodologies resolving dimensionality complications for autism neur...
Cloud computing and distributed systems.
gpt5_lecture_notes_comprehensive_20250812015547.pdf
MYSQL Presentation for SQL database connectivity
Spectroscopy.pptx food analysis technology
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Big Data Technologies - Introduction.pptx

Java Concurrency Gotchas

  • 1. Java Concurrency Gotchas Alex Miller
  • 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 { • Locking • Shared Data • Visibility • Atomicity • Coordination • Safe Publication • Performance
  • 5. Unprotected Field Access A What happens if we modify data without locking?
  • 7. Writer Readers Shared state
  • 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 • Random • Calendar • Pattern • Matcher
  • 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() { if(instance == null) { Attempt to avoid synchronization 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) { READ synchronized(Singleton.class) { if(instance == null) { READ instance = new Singleton(); WRITE } } } return instance; } }
  • 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)) { READ // already present, return existing table.get(key); READ return null; } else { // doesn't exist, create new value WRITE return table.put(key, value); } }
  • 33. Composing atomic actions public Object putIfAbsent( Hashtable table, Object key, Object value) { Hashtable is thread-safe if(table.containsKey(key)) { READ // already present, return existing table.get(key); READ return null; } else { // doesn't exist, create new value WRITE return table.put(key, value); } }
  • 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() All monitors unlocked by ThreadDeath • call Thread.suspend() or Thread.resume() Can lead to deadlock • call Thread.destroy() Not implemented (or safe) • call Thread.run() Wonʼt start Thread! Still in caller Thread. • use ThreadGroups 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 • Deadlock • Performance { • Spin wait • Thread contention
  • 48. Deadlock // Thread 1 synchronized(lock1) { synchronized(lock2) { // stuff } } Classic deadlock. // Thread 2 synchronized(lock2) { synchronized(lock1) { // stuff } }
  • 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) { Thread.sleep(100); Spin on flag, waiting for 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(); Better but longer. } } public void change() { lock.lock(); try { flag = true; condition.signalAll(); } finally { lock.unlock(); } }
  • 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) Hash f(x) Bucket 0 Bucket 1 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 } }
  • 57. Thanks... Twitter http://twitter.com/puredanger Blog http://tech.puredanger.com Concurrency http://concurrency.tumblr.com links http://refcardz.dzone.com/refcardz/ Refcard core-java-concurrency Slides http://slideshare.net/alexmiller