3. 3CONFIDENTIAL
THREAD SAFETY
• … is unfortunately hard to be
defined.
• Because it means different things to
different people!
• Brian Goetz:
• A class is thread-safe when it continues to behave
correctly when accessed from multiple threads.
• Joseph Albahari:
• A program or method is thread-safe if it has no
indeterminacy in the face of any multithreading
scenario.
Image credit: http://www.beaconhillnw.com/2014/09/workplace-safety-signage/
8. 8CONFIDENTIAL
IMMUTABILITY
• Immutable objects cannot change
their state once constructed
• Strategy for definition:
• No setter methods
• All fields private and final
• No methods overriding allowed
• No this and mutable field
references escapes
• Thread safety guaranteed by
initialization safety (JSR-133)
• Safe and simple; consider whenever
feasible
Image credit: https://www.flickr.com/photos/bala_/4184518104/
9. 9CONFIDENTIAL
@ThreadSafe
public final class CreditCard {
private final String holder;
private final String number;
public CreditCard(String holder,
String number) {
this.holder = holder;
this.number = number;
}
public String getHolder() {
return holder;
}
public String getNumber() {
return number;
}
}
THREAD-SAFE
IMMUTABILITY (EXAMPLES)
NOT THREAD-SAFE
@NotThreadSafe
final public class ShoppingCart {
private CartService cartService;
private final List<Item> items;
@Autowired
public ShoppingCart(List<Item> items,
CartService cs) {
cartService = cs;
cartService.registerCart(this);
this.items = Collections
.unmodifiableList(items);
}
public List<Item> getItems() {
return items;
}
}
10. 10CONFIDENTIAL
@ThreadSafe
public final class CreditCard {
private final String holder;
private final String number;
public CreditCard(String holder,
String number) {
this.holder = holder;
this.number = number;
}
public String getHolder() {
return holder;
}
public String getNumber() {
return number;
}
}
THREAD-SAFE
IMMUTABILITY (EXAMPLES)
NOT THREAD-SAFE
@NotThreadSafe
final public class ShoppingCart {
private CartService cartService;
private final List<Item> items;
@Autowired
public ShoppingCart(List<Item> items,
CartService cs) {
cartService = cs;
cartService.registerCart(this);
this.items = Collections
.unmodifiableList(items);
}
public List<Item> getItems() {
return items;
}
} Escape of mutable data object reference
Escape of this reference during construction
11. 11CONFIDENTIAL
EFFECTIVE IMMUTABILITY
• A special case of immutability
• Effective immutability is a
characteristic of instances rather
than classes
• An object instance that cannot be
mutated via any execution path is
effectively immutable
• Effectively immutable objects are
instances of mutable classes
Image credit: https://www.flickr.com/photos/pupski/34237242/
12. 12CONFIDENTIAL
@NotThreadSafe
public final class AirConditioner {
private final boolean canChange;
private short temperature;
public AirConditioner(short temperature, boolean canChange) {
this.canChange = canChange;
this.temperature = temperature;
}
public void setTemperature(short newTemperature) {
if (canChange) {
temperature = newTemperature;
} else {
throw new IllegalStateException();
}
}
public short getTemperature() {
return temperature;
}
}
EFFECTIVE IMMUTABILITY (EXAMPLE)
THREAD-SAFE INSTANCE
AirConditioner airConditioner =
new AirConditioner(24, false);
13. 13CONFIDENTIAL
@NotThreadSafe
public final class AirConditioner {
private final boolean canChange;
private short temperature;
public AirConditioner(short temperature, boolean canChange) {
this.canChange = canChange;
this.temperature = temperature;
}
public void setTemperature(short newTemperature) {
if (canChange) {
temperature = newTemperature;
} else {
throw new IllegalStateException();
}
}
public short getTemperature() {
return temperature;
}
}
EFFECTIVE IMMUTABILITY (EXAMPLE)
THREAD-SAFE INSTANCE
AirConditioner airConditioner =
new AirConditioner(24, false);
14. 14CONFIDENTIAL
COMPARE-AND-SWAP (CAS)
• Non-blocking algorithm for
concurrent access to shared data
• Modifies a value in memory only if
it is equal to a given value,
otherwise the modification fails
• Ensures that the new value is
calculated based on up-to-date
data
• Uses atomic CPU instructions:
• CMPXCHG (x86)
• CMPXCHGQ (x64)
• Available via atomic variables in
Java 5.0+
java.util.concurrent.atomic
Image credit: http://www.keepcalm-o-matic.co.uk/
29. 29CONFIDENTIAL
@ThreadSafe
public class AtomicCounter {
private final AtomicInteger value =
new AtomicInteger(0);
public int getValue() {
return value.get();
}
public int increment() {
return value.incrementAndGet();
}
}
THREAD-SAFE
CAS vs volatile (EXAMPLES)
NOT THREAD-SAFE
@NotThreadSafe
public class VolatileCounter {
private volatile int value = 0;
public int getValue() {
return value;
}
public int increment() {
return value++;
}
}
30. 30CONFIDENTIAL
@ThreadSafe
public class AtomicCounter {
private final AtomicInteger value =
new AtomicInteger(0);
public int getValue() {
return value.get();
}
public int increment() {
return value.incrementAndGet();
}
}
THREAD-SAFE
CAS vs volatile (EXAMPLES)
NOT THREAD-SAFE
@NotThreadSafe
public class VolatileCounter {
private volatile int value = 0;
public int getValue() {
return value;
}
public int increment() {
return value++;
}
} • Unsafe operation
• The increment operator is not an
atomic action:
• Read value
• Increment by 1
• Write value
• Volatile ensures visibility only and not
atomicity
31. 31CONFIDENTIAL
@ThreadSafe
public class VolatileCounter {
private volatile int value = 0;
public int getValue() {
return value;
}
public synchronized int increment() {
return value++;
}
}
@ThreadSafe
public class AtomicCounter {
private final AtomicInteger value =
new AtomicInteger(0);
public int getValue() {
return value.get();
}
public int increment() {
return value.incrementAndGet();
}
}
THREAD-SAFE
CAS vs volatile (EXAMPLES)
THREAD-SAFE
Lock contention == performance degradation
32. 32CONFIDENTIAL
VOLATILE PIGGY-BACKING
• Allows volatile-like semantics for non-volatile variables
• Exploits the happens-before order established by JSR-133
• Actions in the same thread cannot be reordered (Program order)
• A write to a volatile field
happens-before every
subsequent read of that field
• Volatile writes effectively
create a memory fence
which flushes CPU cache
Image credit: http://www.magic-of-color.com/?p=2127
33. 33CONFIDENTIAL
public class Point {
private int x;
private int y;
private volatile boolean done = false;
public void calculateCoordinates() {
x = someHeavyweightAlgorithm(…); // x=5
y = someHeavyweightAlgorithm(…); // y=10
sync();
}
private void sync() {
done = true;
}
public int getX() { return x; }
public int getY() { return y; }
public boolean isDone() { return done; }
}
THREAD #1
VOLATILE PIGGY-BACKING (EXAMPLE)
THREAD #2
public class CoordinatesConsumer {
private Point point;
public CoordinatesConsumer(Point point) {
this.point = point;
}
public void doSomething() {
while (!point.isDone()) ; // Busy wait
int x = point.getX(); // x=5
int y = point.getY(); // y=10
}
}
• x and y get visible in Thread #2 even
though they are not volatile
• they piggyback on done which is volatile
34. 34CONFIDENTIAL
VOLATILE PIGGY-BACKING PRECAUTIONS
• Volatile piggybacking is fragile! Use at your own risk!
• Ensures only visibility, thus applicable for “single writer /
multiple readers” scenarios only
• It does not ensure compound atomicity in case of multiple
writes/reads.
Image credit: http://www.noomii.com/blog/5949-warning-union-info-centre-scam
35. 35CONFIDENTIAL
THREAD CONFINEMENT
• Thread confinement is a simple yet powerful technique used
to achieve thread safety without synchronization.
• The simple idea:
• If data is only accessed from a single thread,
no synchronization is needed.
• Examples:
• Swing – visual components are confined to the event
dispatch thread
• JDBC Connection Pools
36. 36CONFIDENTIAL
CONFINEMENT MECHANISMS
• Java does not provide language-level
mechanisms that enforce thread
confinement.
• Must be enforced by the application
design and its implementation
• Java provides mechanisms that help maintaining confinement:
• Access modifiers
• Local variables
• ThreadLocal
Image credit: http://www.treatmentadvocacycenter.org/about-us/our-blog/69-no-state/2109-solitary-confinement-like-gasoline-on-fire
37. 37CONFIDENTIAL
AD-HOC THREAD CONFINEMENT
• Developer is completely responsible to confine object to
thread. Language features (like local variables, access
modifiers) are not used
• State must be shared in a specific way:
• All shared data – marked as volatile
• Only a single thread must be able to write to the
shared data - requires developer’s carefulness and
discipline
• Not recommended approach (due to its fragility)
38. 38CONFIDENTIAL
STACK CONFINEMENT
• Special case of thread
confinement
• An object can only be
reached through a
local variable
• The developer must
ensure that the object
reference does not
escape the method
• Ensures thread safety even if the confined object itself is not
thread-safe
39. 39CONFIDENTIAL
STACK CONFINEMENT
• Example:
public static String format(Date date) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
return df.format(date);
}
• We only have one reference to the SimpleDateFormat object
• The reference is held in a local variable and therefore confined
to the executing thread
41. 41CONFIDENTIAL
STACK CONFINEMENT
private static final DateFormat df =
new SimpleDateFormat("yyyy-MM-dd");
public static String format(Date date) {
return df.format(date);
}
No longer
“stack confined”
42. 42CONFIDENTIAL
THREAD CONFINEMENT WITH ThreadLocal
java.lang.ThreadLocal<T>:
• Provides thread-local variables
• Each thread has its own, independently initialized copy
of the variable (accessed via ThreadLocal’s get() or
set() methods)
• ThreadLocal instances are typically private static fields
in classes that wish to associate state with a thread
43. 43CONFIDENTIAL
THREAD CONFINEMENT WITH ThreadLocal
Example: DateFormat is not thread-safe, so we use thread
confinement:
private static final ThreadLocal<DateFormat> tdf =
new ThreadLocal<DateFormat>() {
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
public String threadConfined(Date date) {
return tdf.get().format(date);
}
44. 44CONFIDENTIAL
OBJECT ESCAPE
• An object is said to have escaped if it is published before
intended.
Image credit: http://www.humbersidefire.gov.uk/your-safety/safety-in-the-home/escape
45. 45CONFIDENTIAL
OBJECT ESCAPE (EXAMPLE)
• Store a reference in a public static field, where any class and thread
could see it:
public static List<String> unsafeList;
public void initialize() {
unsafeList = new ArrayList<String>();
}
• Return a reference from a non-private method:
class UnsafeCurrencies {
private String[] currencies = new String[] {"USD",
"GBP", "BGN", "EUR", "AUD"};
public String[] getCurrencies() { return currencies; }
}
46. 46CONFIDENTIAL
JAVA
OBJECT ESCAPE (EXAMPLE)
BYTECODE
…
final com.threadconfinement.ThisEscape this$0;
…
0: aload_0
1: aload_1
2: putfield #1
// Field this$0:Lcom/threadconfinement/ThisEscape;
5: aload_0
6: invokespecial #2
// Method java/lang/Object."<init>":()V
9: return
…
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
47. 47CONFIDENTIAL
JAVA
OBJECT ESCAPE (EXAMPLE)
BYTECODE
…
final com.threadconfinement.ThisEscape this$0;
…
0: aload_0
1: aload_1
2: putfield #1
// Field this$0:Lcom/threadconfinement/ThisEscape;
5: aload_0
6: invokespecial #2
// Method java/lang/Object."<init>":()V
9: return
…
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
48. 48CONFIDENTIAL
BENEFITS
• No accidental complexitySIMPLICITY2
1
• No lock contention
• Scales really well due to the lack of
synchronization overhead
PERFORMANCE
& SCALABILITY
3 • No race conditions
NO RISK OF
DEADLOCKS