Concurrent programming without synchronization
-
Upload
martin-hristov -
Category
Documents
-
view
173 -
download
0
Transcript of Concurrent programming without synchronization
![Page 1: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/1.jpg)
1CONFIDENTIAL
CONCURRENT PROGRAMMING
WITHOUT SYNCHRONIZATION
JENI MARKISHKA
MARTIN HRISTOVJULY 4, 2015
![Page 2: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/2.jpg)
2CONFIDENTIAL
THREAD SAFETY?
WHAT IS
![Page 3: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/3.jpg)
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/
![Page 4: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/4.jpg)
4CONFIDENTIAL
ALL ABOUT DATA INTEGRITY!
THREAD SAFETY IS
![Page 5: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/5.jpg)
5CONFIDENTIAL
THREAD SAFETY?
BUT HOW DO WE ACHIEVE
![Page 6: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/6.jpg)
6CONFIDENTIAL
THREAD SAFETY?
BUT HOW DO WE ACHIEVE
> MUTEXES
> LOCK-FREE MECHANISMS
![Page 7: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/7.jpg)
7CONFIDENTIAL
LOCK-FREE THREAD SAFETY
Immutability1
Compare-And-Swap (CAS)2
volatile piggy-backing3
Thread confinement4
• Ad-hoc Thread Confinement
• Stack Confinement
• Thread Confinement with ThreadLocal
![Page 8: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/8.jpg)
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/
![Page 9: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/9.jpg)
9CONFIDENTIAL
@ThreadSafepublic 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
@NotThreadSafefinal public class ShoppingCart {
private CartService cartService;private final List<Item> items;
@Autowiredpublic ShoppingCart(List<Item> items,
CartService cs) {cartService = cs;cartService.registerCart(this);this.items = Collections
.unmodifiableList(items);}
public List<Item> getItems() {return items;
}}
![Page 10: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/10.jpg)
10CONFIDENTIAL
@ThreadSafepublic 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
@NotThreadSafefinal public class ShoppingCart {
private CartService cartService;private final List<Item> items;
@Autowiredpublic 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
![Page 11: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/11.jpg)
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/
![Page 12: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/12.jpg)
12CONFIDENTIAL
@NotThreadSafepublic 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);
![Page 13: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/13.jpg)
13CONFIDENTIAL
@NotThreadSafepublic 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);
![Page 14: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/14.jpg)
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/
![Page 15: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/15.jpg)
15CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
CPU2
![Page 16: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/16.jpg)
16CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
CPU2
read
![Page 17: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/17.jpg)
17CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
read
21
![Page 18: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/18.jpg)
18CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
![Page 19: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/19.jpg)
19CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
read
![Page 20: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/20.jpg)
20CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
21
read
ok
![Page 21: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/21.jpg)
21CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
21
![Page 22: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/22.jpg)
22CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
2122
![Page 23: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/23.jpg)
23CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
22
CPU2
21
cas(21,22)
![Page 24: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/24.jpg)
24CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
21
cas(21,22)
22
ok
2222
![Page 25: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/25.jpg)
25CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
21
22
2222
22
![Page 26: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/26.jpg)
26CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
21
22
2222
22
20
![Page 27: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/27.jpg)
27CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
21
22
2222
22
20
cas(21,20)
![Page 28: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/28.jpg)
28CONFIDENTIAL
CPU1
CAS EXPLAINED
MEMORY
21
21
CPU2
21
22
2222
22
20
cas(21,20)
write
failed
![Page 29: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/29.jpg)
29CONFIDENTIAL
@ThreadSafepublic 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
@NotThreadSafepublic class VolatileCounter {
private volatile int value = 0;
public int getValue() {return value;
}
public int increment() {return value++;
}}
![Page 30: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/30.jpg)
30CONFIDENTIAL
@ThreadSafepublic 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
@NotThreadSafepublic 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
![Page 31: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/31.jpg)
31CONFIDENTIAL
@ThreadSafepublic class VolatileCounter {
private volatile int value = 0;
public int getValue() {return value;
}
public synchronized int increment() {return value++;
}}
@ThreadSafepublic 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
![Page 32: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/32.jpg)
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
![Page 33: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/33.jpg)
33CONFIDENTIAL
public class Point {
private int x;private int y;
private volatile boolean done = false;
public void calculateCoordinates() {x = someHeavyweightAlgorithm(…); // x=5y = someHeavyweightAlgorithm(…); // y=10sync();
}
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 waitint x = point.getX(); // x=5int 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
![Page 34: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/34.jpg)
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
![Page 35: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/35.jpg)
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
![Page 36: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/36.jpg)
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
![Page 37: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/37.jpg)
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)
![Page 38: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/38.jpg)
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
![Page 39: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/39.jpg)
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
![Page 40: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/40.jpg)
40CONFIDENTIAL
STACK CONFINEMENT
private static final DateFormat df =
new SimpleDateFormat("yyyy-MM-dd");
public static String format(Date date) {
return df.format(date);
}
![Page 41: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/41.jpg)
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”
![Page 42: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/42.jpg)
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
![Page 43: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/43.jpg)
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);
}
![Page 44: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/44.jpg)
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
![Page 45: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/45.jpg)
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; }
}
![Page 46: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/46.jpg)
46CONFIDENTIAL
JAVA
OBJECT ESCAPE (EXAMPLE)
BYTECODE
…final com.threadconfinement.ThisEscape this$0;
…0: aload_01: aload_12: putfield #1// Field this$0:Lcom/threadconfinement/ThisEscape;5: aload_06: invokespecial #2// Method java/lang/Object."<init>":()V9: return…
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
![Page 47: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/47.jpg)
47CONFIDENTIAL
JAVA
OBJECT ESCAPE (EXAMPLE)
BYTECODE
…final com.threadconfinement.ThisEscape this$0;
…0: aload_01: aload_12: putfield #1// Field this$0:Lcom/threadconfinement/ThisEscape;5: aload_06: invokespecial #2// Method java/lang/Object."<init>":()V9: return…
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
![Page 48: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/48.jpg)
48CONFIDENTIAL
BENEFITS
• No accidental complexitySIMPLICITY2
1
• No lock contention
• Scales really well due to the lack of
synchronization overhead
PERFORMANCE
& SCALABILITY
3 • No race conditionsNO RISK OF
DEADLOCKS
![Page 49: Concurrent programming without synchronization](https://reader034.fdocuments.net/reader034/viewer/2022051318/58ef5b5c1a28ab460c8b45f9/html5/thumbnails/49.jpg)
49CONFIDENTIAL
THE END