صفحه 1:
3
Java™ Platform
Concurrency Gotchas
Java 15 a trademark of Sun Microsystems, Inc.
Alex Miller
Terracotta
صفحه 2:
۱۳۱/۸۰۵
Questions to answer
> What are common concurrency problems?
> Why are they problems?
> How do | detect these problems?
> How do | correct these problems?
@ Sun
صفحه 3:
۱۳۱/۰۵
Taxonomy of Concurrency Gotchas
> Shared Data
> Coordination
> Performance
@ Sun
صفحه 4:
۱۳۱/۰۵
Shared Data
> Locking
> Visibility
> Atomicity
> Safe Publication
@ Sun
صفحه 5:
۱۳۱/۰۵
What happens if we modify
data without locking?
@ Sun
صفحه 6:
۱۳۱/۰۵
What happens if we modify
data without locking?
@ Sun
صفحه 7:
غ2 ی 1 -
2 5
3
1۸۱2۱/۱20
صفحه 8:
۱۳۱/۸۰۵
Mutable Statics
public class MutableStatics { [FORMAT Es mutable J @)
private static final DateFormat FORMAT =
DateFormat.getDateInstance (DateFormat .MEDIUM) ;
public static Date parse(String str)
throws ParseException {
return FORMAT .parse (str) ; eee |
}
public static void main(String arg[]) {
MutableStatics.parse (“Jan 1, 2000”);
}
@ Sun
صفحه 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”);
صفحه 10:
۱۳۱/۰۵
synchronization
private int myField;
myField = 0;
}
@ Sun
صفحه 11:
JavaOne
DO NOT synchronize on null
MyObject obj = null; ©
synchronized ( obj ) ) 01
// stuff
}
@ Sun
صفحه 12:
JavaOne
DO NOT change instance
MyObject obj = new MyObject() ;
synchronized( obj ) {
@ Sun
صفحه 13:
@ Sun یز 5
microsystems
صفحه 14:
JavaOne
DO NOT synchronize on string literals
private static final String LOCK = “LOCK”; ©
synchronized( LOCK ) {
@ Sun
صفحه 15:
JavaOne
DO NOT synchronize on autoboxed instances
private static final Integer LOCK = 0; ۵
synchronized( LOCK ) {
@ Sun
صفحه 16:
۱۳۱/۸۰۵
DO NOT synchronize on ReentrantLock
final Lock lock = new ReentrantLock() ; ۵
synchronized( lock ) {
}
final Lock lock = new ReentrantLock () ;
lock .lock () ; 0
/7 ex
} finally {
lock .unlock () ;
}
@ Sun
صفحه 17:
JavaOne
What should | 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
@ Sun
صفحه 18:
۱۳۱/۰۵
Visibility
صفحه 19:
۱۳۱/۸۰۵
Inconsistent Synchronization
public class SomeData { ۵
private final Map data = new HashMap () ;
public void put(String key, String value) {
synchronized(data) {
}
public String get(String key) {
}
صفحه 20:
۱۳۱/۸۰۵
Double-checked locking
public final class Singleton {
private static Singleton instance;
public static Singleton getInstance() {
synchronized (Singleton.class) 1
if (instance == null) {
instance = new Singleton () ;
}
return instance;
صفحه 21:
JavaOne
Double-checked locking
public final class Singleton {
private static Singleton instance;
public static Singleton getInstance() {
if (instance == null) { READ
synchronized (Singleton.class) 1
if (instance == null) { READ
instance = new Singleton () ; WRITE
}
}
return instance;
صفحه 22:
JavaOne
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 ) 7
}
return INSTANCE;
@ Sun
صفحه 23:
JavaOne
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:
JavaOne
Racy single-check
public final class String { 0
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;
@ Sun
22
صفحه 25:
۱۳۱/۸۰۵
volatile arrays
public final class VolatileArray {
private volatile boolean[] vals;
public void flip(int i) {
wees in oer esaer
}
public boolean flipped(int i) {
return vals[i];
@ Sun
23
صفحه 26:
۱۳۱/۰۵
Atomicity
@ Sun
صفحه 27:
JavaOne
Volatile counter
public class Counter {
private volatile int count; ©
public int next() {
}
@ Sun
صفحه 28:
JavaOne
AtomiclInteger counter
public class Counter {
private final AtomicInteger count = new AtomicInteger () ;
public int next() {
return count.getAndIncrement () ;
صفحه 29:
۱۳۱/۸۰۵
Composing atomic actions
public Object putIfAbsent (
Hashtable table, Object key, Object value) { ۵
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;
@ Sun 0
صفحه 30:
۱۳۱/۸۰۵
Composing atomic actions
public Object putIfAbsent (
Hashtable table, Object key, Object value) { ۵
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;
@ Sun 0
صفحه 31:
۱۳۱/۸۰۵
Participate in lock
public Object putIfAbsent (
Hashtable table, Object key, Object value) { ©
if (table.containsKey(key)) {
return table.get (key) ;
} else {
table.put (key, value) ;
return value;
@ Sun
28
صفحه 32:
JavaOne
Encapsulated compound actions
public Object putIfAbsent (
ConcurrentHashMap table, Object key, Object value) {
table .putIfAbsent (key, value) ;
@ Sun
صفحه 33:
JavaOne
Assignment of 64 bit values
public class LongAssignment {
private long x; ©
public void setLong(long val) {
}
@ Sun
30
صفحه 34:
۱۳۱/۰۵
Assignment of 64 bit values - volatile
public class LongAssignment {
private volatile long x; ©
public void setLong(long val) {
x = val;
@ Sun
صفحه 35:
۱۳۱/۰۵
Safe publication
Intentionally left blank.
@ Sun 0
صفحه 36:
۱۳۱/۸۰۵
Listener in constructor
public interface DispatchListener {
void newFare (Customer customer) ; ۵
public class Taxi implements DispatchListener {
public Taxi(Dispatcher dispatcher) {
dispatcher.registerListener (this) ;
}
public void newFare (Customer customer) {
// go to new customer's location
by 33
rasystems
صفحه 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
@ Sun
34
صفحه 38:
JavaOne
Static factory method
public class Cache {
i. ©)
public static Cache newCache() {
Cache cache = new Cache () ;
cache.startCleanerThread () ;
return cache;
@ Sun
35
صفحه 39:
JavaOne
Coordination
> Threads
> wait/notify 1m in ur fizx lab
@ Sun
صفحه 40:
JavaOne
Threads
> DO NOT:
e Call Thread.stop()
e Call Thread.suspend() or Thread.resume()
e Call Thread.destroy()
e Call Thread.run()
e Use ThreadGroups
@ Sun
صفحه 41:
۱۳۱/۰۵
wait/notify
// Thread 1
synchronized(lock) { ©
while(! someCondition()) {
lock.wait() ;
// Thread 2
synchronized (lock) { |Synchronize here too. |
satisfyCondition () ; Update condition! |
lock .notifyAl11 () ;
@ Sun
38
صفحه 42:
۱۳۱/۰۵
Performance
> Deadlock
> Spin wait
> Lock contention
@ Sun
صفحه 43:
JavaOne
Deadlock
// Thread 1
synchronized(locki) { 69
// stuff
// Thread 2
synchronized(lock2) {
synchronized(locki) {
// stuff
}
@ Sun
40
صفحه 44:
۱۳۱/۰۵
Deadlock avoidance
> Lock splitting
> Lock ordering
> Lock timeout
> tryLock
@ Sun
صفحه 45:
۱۳۱/۰۵
Spin wait
// Not efficient
private volatile boolean flag
public void waitTillChange() {
false; 69
while(! flag) 1
Thread.sleep (100) ; See ea
public void change() {
flag = true;
@ Sun
42
صفحه 46:
۱۳۱/۸۰۵
/ص111 0 ۷/۱۲۲۱ ۳۱60۱206
private final Object lock < ۷ 0عدطه )(
private boolean flag = false; ©
public void waitTillChange() {
synchronized(lock) {
while(! flag)
lock .wait();
}
public void change() {
synchronized(lock) {
flag = true;
lock .notifyAl1l1 () ;
43
صفحه 47:
۱۳۱/۸۰۵
Lock contention
سس
Bucket 0 Bucket 1 Bucket 2 Bucket 3
@ Sun ۲
صفحه 48:
JavaOne
Lock striping
@ Sun
صفحه 49:
46
long
۱۳۱/۸۰۵
Final Exam
public class StatisticsImpl implements Statistics,
StatisticsImplementor {
private long queryExecutionCount;
public synchronized void queryExecuted (String hql, int rows,
time) {
queryExecutionCountt+;
// ... other stat collection
public long getQueryExecutionCount() {
return queryExecutionCount;
public synchronized void clear() {
queryExecutionCount = 0;
// ... clear all other stats
}
}
@ Sun
microsystems
صفحه 50:
۱۳۱/۸۰۵
Final Exam
public class StatisticsImpl implements Statistics,
StatisticsImplementor { ۵
private long queryExecutionCount;
public synchronized void queryExecuted(String hql, int rows, long
time) {
queryExecutionCountt+;
// ... other stat collection
public long getQueryExecutionCount() {
return queryExecutionCount;
}
public synchronized void clear() {
queryExecutionCount = 0;
// ... clear all other stats
}
}
& Sun 7
microsystems
صفحه 51:
۱۳۱/۸۰۵
Final Exam
public class StatisticsImpl implements Statistics,
StatisticsImplementor { ۵
private long queryExecutionCount;
public synchronized void queryExecuted(String hql, int rows, long
time) {
queryExecutionCountt+;
// ... other stat collection
public long getQueryExecutionCount() {
return queryExecutionCount;
} |
public synchronized void clear() {
queryExecutionCount = 0;
// ... clear all other stats
}
& Sun 7
microsystems
صفحه 52:
۱۳۱/۸۰۵
Final Exam
public class StatisticsImpl implements Statistics,
StatisticsImplementor { ۵
private long queryExecutionCount;
public synchronized void queryExecuted(String hql, int rows, long
time) {
queryExecutionCountt+;
// ... other stat collection
public long getQueryExecutionCount() {
return queryExecutionCount;
}
public synchronized void clear() {
queryExecutionCount = 0;
// ... clear all other stats
}
}
@ Sun 1
صفحه 53:
۱۳۱/۸۰۵
Final Exam
public class StatisticsImpl implements Statistics,
StatisticsImplementor { ۵
private long queryExecutionCount;
public synchronized void queryExecuted(String hql, int rows, long
en ‘Single shared lock for ALL stat values |
queryExecutionCountt+;
// ... other stat collection
public long getQueryExecutionCount() {
return queryExecutionCount;
}
public synchronized void clear() {
queryExecutionCount = 0;
// ... clear all other stats
}
}
@ Sun 1
صفحه 54:
JavaOne
Alex Miller
Terracotta
Blog: _ http://tech.puredanger.com
Twitter: @puredanger
