Java Concurrency Gotchas

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    10 Favorites

    Java Concurrency Gotchas - Presentation Transcript

    1. Java™ Platform Concurrency Gotchas Alex Miller Terracotta
    2. Questions to answer > What are common concurrency problems? > Why are they problems? > How do I detect these problems? > How do I correct these problems? 2
    3. Taxonomy of Concurrency Gotchas > Shared Data > Coordination > Performance 3
    4. Shared Data > Locking > Visibility > Atomicity > Safe Publication 4
    5. What happens if we modify data without locking? 5
    6. What happens if we modify data without locking? Hint: itʼs not good. 5
    7. 6
    8. 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 { ...and this mutates it return FORMAT.parse(str); outside synchronization } public static void main(String arg[]) { MutableStatics.parse(“Jan 1, 2000”); } } 7
    9. 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[]) { MutableStatics.parse(“Jan 1, 2000”); } } 8
    10. Synchronization private int myField; synchronized( What goes here? ) { myField = 0; } 9
    11. DO NOT synchronize on null MyObject obj = null; synchronized( obj ) { NullPointerException! // stuff } 10
    12. DO NOT change instance MyObject obj = new MyObject(); synchronized( obj ) { No longer synchronizing obj = new MyObject(); on the same object! } 11
    13. 12
    14. DO NOT synchronize on string literals private static final String LOCK = “LOCK”; synchronized( LOCK ) { What is the scope // work of LOCK? } 13
    15. DO NOT synchronize on autoboxed instances private static final Integer LOCK = 0; synchronized( LOCK ) { What is the scope // work of LOCK? } 14
    16. DO NOT synchronize on ReentrantLock final Lock lock = new ReentrantLock(); synchronized( lock ) { Probably not what // work you meant here } final Lock lock = new ReentrantLock(); lock.lock(); Probably should try { be this instead // ... } finally { lock.unlock(); } 15
    17. What should I lock on? // The field you are protecting private final Map map = ... synchronized(map) { // ...access map } // Or an explicit lock object private final Object lock = new Object(); synchronized(lock) { // ... modify state } 16
    18. Visibility 17
    19. Inconsistent Synchronization public class SomeData { private final Map data = new HashMap(); public void put(String key, String value) { synchronized(data) { data.put(key, value); Modified under synchronization } } public String get(String key) { return data.get(key); Read without synchronization } } 18
    20. Double-checked locking public final 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; } } 19
    21. Double-checked locking public final 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; } } 19
    22. 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; } 20
    23. 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; } } 21
    24. Racy single-check public final class String { private int hash; // default to 0 private final char[] value; // immutable public int hashCode() { int h = hash; if(h == 0) { // ... compute value for h from data hash = h; } return h; } } 22
    25. volatile arrays public final class VolatileArray { private volatile boolean[] vals; public void flip(int i) { vals[i] = true; Is the value of vals[i] } visible to other threads? public boolean flipped(int i) { return vals[i]; } } 23
    26. Atomicity 24
    27. Volatile counter public class Counter { private volatile int count; public int next() { return count++; Looks atomic to me! } } 25
    28. AtomicInteger counter public class Counter { private final AtomicInteger count = new AtomicInteger(); public int next() { Really atomic by return count.getAndIncrement(); encapsulating } multiple actions } 26
    29. 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 value return table.get(key); READ } else { // doesn’t exist, create and return new value table.put(key, value); WRITE return value; } } 27
    30. 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 value return table.get(key); READ } else { // doesn’t exist, create and return new value table.put(key, value); WRITE return value; } } 27
    31. Participate in lock public Object putIfAbsent( Hashtable table, Object key, Object value) { synchronized(table) { Protect with synchronization if(table.containsKey(key)) { return table.get(key); } else { table.put(key, value); return value; } } } 28
    32. Encapsulated compound actions public Object putIfAbsent( ConcurrentHashMap table, Object key, Object value) { table.putIfAbsent(key, value); } 29
    33. 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? } 30
    34. Assignment of 64 bit values - volatile public class LongAssignment { private volatile long x; public void setLong(long val) { x = val; } } 31
    35. Safe publication Intentionally left blank. 32
    36. 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 } } 33
    37. Starting thread in constructor public class Cache { private final Thread cleanerThread; public Cache() { this escapes again! cleanerThread = new Thread(new Cleaner(this)); cleanerThread.start(); } // Cleaner calls back to this method public void cleanup() { // clean up Cache } } 34
    38. Static factory method public class Cache { // ... public static Cache newCache() { Cache cache = new Cache(); cache.startCleanerThread(); return cache; } } 35
    39. Coordination > Threads > wait/notify 36
    40. Threads > DO NOT: • Call Thread.stop() • Call Thread.suspend() or Thread.resume() • Call Thread.destroy() • Call Thread.run() • Use ThreadGroups 37
    41. 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(); Update condition! lock.notifyAll(); } 38
    42. Performance > Deadlock > Spin wait > Lock contention 39
    43. Deadlock // Thread 1 synchronized(lock1) { synchronized(lock2) { Classic deadlock. // stuff } } // Thread 2 synchronized(lock2) { synchronized(lock1) { // stuff } } 40
    44. Deadlock avoidance > Lock splitting > Lock ordering > Lock timeout > tryLock 41
    45. Spin wait // Not efficient private volatile boolean flag = false; public void waitTillChange() { while(! flag) { Spin on flag, Thread.sleep(100); waiting for change } } public void change() { flag = true; } 42
    46. Replace with wait/notify private final Object lock = new Object(); private boolean flag = false; public void waitTillChange() { synchronized(lock) { while(! flag) Wait/notify is far more lock.wait(); efficient than spin wait. } } public void change() { synchronized(lock) { flag = true; lock.notifyAll(); } } 43
    47. Lock contention x Hash f(x) Bucket 0 Bucket 1 Bucket 2 Bucket 3 44
    48. Lock striping x Hash g(x) Hash f(x) Hash f(x) Bucket 0 Bucket 1 Bucket 0 Bucket 1 45
    49. 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 } } 46
    50. 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; Read of shared value } without synchronization public synchronized void clear() { queryExecutionCount = 0; // ... clear all other stats } } 46
    51. 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; Read of shared value Non-atomic read } without synchronization of long value public synchronized void clear() { queryExecutionCount = 0; // ... clear all other stats } } 46
    52. 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; Read of shared value Non-atomic read } without synchronization of long value public synchronized void clear() { queryExecutionCount = 0; Race condition if reading stat and // ... clear all other stats clearing - could be compound action } } 46
    53. Final Exam public class StatisticsImpl implements Statistics, StatisticsImplementor { private long queryExecutionCount; public synchronized void queryExecuted(String hql, int rows, long time) { Single shared lock for ALL stat values queryExecutionCount++; // ... other stat collection } public long getQueryExecutionCount() { return queryExecutionCount; Read of shared value Non-atomic read } without synchronization of long value public synchronized void clear() { queryExecutionCount = 0; Race condition if reading stat and // ... clear all other stats clearing - could be compound action } } 46
    54. Alex Miller Terracotta Blog: http://tech.puredanger.com Twitter: @puredanger
    SlideShare Zeitgeist 2009

    + Alex MillerAlex Miller Nominate

    custom

    1806 views, 10 favs, 4 embeds more stats

    An overview of Java Concurrency bug patterns. Java more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 1806
      • 1651 on SlideShare
      • 155 from embeds
    • Comments 0
    • Favorites 10
    • Downloads 30
    Most viewed embeds
    • 123 views on http://tech.puredanger.com
    • 17 views on http://puredanger.com
    • 12 views on http://www.net4java.com
    • 3 views on http://fujohnwang.appspot.com

    more

    All embeds
    • 123 views on http://tech.puredanger.com
    • 17 views on http://puredanger.com
    • 12 views on http://www.net4java.com
    • 3 views on http://fujohnwang.appspot.com

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories