Upload
others
View
5
Download
0
Embed Size (px)
Citation preview
The Java Memory Model
What is it and why would I want one?
Jörg Domaschka. ART Group,
Institute for Distributed Systems
Ulm University, Germany December 14, 2009
public class WhatDoIPrint{
static int x = 0, y = 0, a = 0, b = 0;
public static void main(String[] args){
Thread one = new Thread(new Runnable(){
public void run(){
a = 1;
x = b;
} )};
Thread other = new Thread(new Runnable(){
public void run(){
b = 1;
y = a;
} )};
one.start(); other.start();
one.join(); other.join();
System.out.println(„( “ + x + „, “ + y + „ )“);
}
Possible Results
• Obviously: (1,0), (1,1), (0,1)
• Surprisingly: (0,0)
Why that?
Code reordering
x = b (0)
b = 1 y = a (0)
a = 1reorder
Reorderings
Every entity optimises heavily
• Compiler
• Processor
• Caches
In our case
• No shared variables declared
• Optimise for local operation
Outline
• Motivation
• JMM in a Nutshell
• The final Keyword
• Conclusions
Definitions
Memory Model:
• Specifies when actions of one thread on memory are guaranteed to be visible by others.
• Defines:
– What you can expect from the system
– Operations for additional support
• Used in– Multi-core/cpu architecture
– Multi-level caching
Java Memory Model
• Minimal guarantees the JVM must make about when writes to variables become visible.
predictability and ease of programmingvs
high-performance
• What can we expect?
• Which additional operations do we have?
What to Expect?
Sequential Consistency
• Mental model of many programmers
• A happy, if unrealistic model [Goetz]
• The von Neumann model is only a vague approximation [Goetz]
What to Expect?
In the absence of special operations:
• Java provides barely any inter-thread guarantees
• Execution of a single thread is as-if sequential
Don‘t expect anything
• Unless you prepared for it
Special Operations?
• In JMM
– Threads execute actions
– Actions are partially ordered(happens-before: antisymmetric, reflexive, transitive)
– Default: actions of different threads are not ordered
Special Actions!
Inter-thread ordering actions
– Lock/unlock on monitor
– Volatile variables
– Thread start/termination/interruption
– ...
– Synchronize all caches with main memory(Piggybacking on synchronization is possible)
Define a synchronizes-with relation
Synchronisation Actions
• Totally ordered
– With respect to a single mutex/volatile variable
– No ordering guarantees for distinct variables
• Synchronized programmes
– Data race: Conflicting access to a shared variable that is not synchronized
– Correctly synchronized: All sequentially consistent executions are free of data races
Correct or Not?
Thread 1:
X = 1;
Lock M1;
Y = 1;
Unlock M1;
Thread 2:
Lock M1;
i = Y;
Unlock M1;
j = X;
Correct or Not?
Thread 1:
X = 1
Lock M1
Y = 1
Unlock M1
Lock M1
i = Y
Unlock M1
j = X
Thread 2:
Correct or Not?
Thread 1:
X = 1
Lock M1
Y = 1
Unlock M1
Lock M1
i = Y
Unlock M1
j = X
Thread 2:
Best Practices - Locking
Every shared, mutable variable
• Guarded by exactly one lock
Invariants that involve multiple variables
• All variables must be guarded by the same lock
• Resist the temptation to prematurely sacrifice simplicity for the sake of performance.
Best Pratices - volatile
Volatile variables can only guarantee visibility.
• Writes must not depend on current value
• Does not participate in invariants
• Locking is not required for other reasons
Outline
• Motivation
• JMM in a Nutshell
• The final Keyword
• Conclusions
The final Keyword
Semantics of final Fields
• Initialised once
• Never changed under normal circumstances
Allows for compiler optimisations
• Do not depend on memory barriers (i.e., locks)
• Can always be cached
Benefit: thread-safe immutable objects
final‘s Effect on Memory
• Freezing final fields
– At end of constructor
• But not before
– Reading a final field by constructing thread beforefreeze yields default value
• Allows building immutable objects
– Vital to Java security architecture
– Strings must not change
final‘s Visibility Guarantees
• After freeze of Object o– All threads see correct value of final fields…
– … and fields exclusively reachable through them
– … if they obtained reference to o after the freeze
• Non-final fields– Only guaranteed to bee seen correctly by finalizer
– Unless synchronisation is used
Requires safe publication of objects
Example
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample(){
x = 3;
y = 4;
}
static void reader(){
if (f != null){
int i = f.x;
int j = f.y;
}
}
static void writer(){
f = new FinalFieldExample();
}
}
Example - Publication
class UnsafeLazyInitialisation{
private static Resource resouce;
public static Resource getInstance(){
if(resource == null)
resource = new Resource();
return resource;
}
}
Example – Publication (II)
class SafeLazyInitialisation{
private static Resource resouce;
public synchronized static Resource getInstance(){
if(resource == null)
resource = new Resource();
return resource;
}
}
Example – Publication (III)
class EagerInitialisation{
private static Resource resouce = new Resource();
public synchronized static Resource getInstance(){
return resource;
}
}
Example – Publication (IV)
class ResourceFactory{
private static class ResourceHolder {
public static Resource resource = new Resource();
}
public synchronized static Resource getInstance(){return ResourceHolder.resource;
}
}
Example – Publication (V)
pulic Holder holder;
public void initialise(){
holder = new Holder(42);
}
public class Holder {
private int n;
public Holder(int i) {
n = i;
}
public void assertSanity(){
assert n == n : „This statement is false“;
}
}
Best Practices – Sharing ObjectsConsider local variables/object• No concurrency possible
Consider using ThreadLocal
• One value per thread
Use immutable objects where possible• Immutable objects are always thread-safe• If published correctly
Make use of final• Effect on visibility• Easier reasoning about correctness
Best Practices - Publication
Do not allow this references to escape during construction
• Consider using factory methods
• Do not start a thread from a constructor
• Use inheritance judiciously
• Publish safely
Best Practices – Safe Publication
Publish object reference and object state at the same time
• Static initialiser
• Write to volatile field or AtomicReference
• Store reference into a final field
• Store reference to a field guarded by a lock
Placing an object in a unsynchronized Collection does not work in general
Outline
• Motivation
• Definitions
• JMM in a Nutshell
• The final Keyword
• Conclusions
Beyond Synchronisation
• JMM also defines
– Which reads/writes have to be atomic
– Semantics of wait and notify operations
• Parallel to interrupts
• Neither interrupt nor notify must get lost
– Semantics of sleep and yield
• Do not have any synchronisation semantics
– Semantics of modifying final fields
Conclusions
• JMM specifies when actions of one thread are guaranteed to be visible to another
• Threads run isolated: no guarantees
• Synchronisation actions provide inter-thread dependencies
Conclusions (II)
• final fields provide stronger guarantees(freeze when constructor finishes)
• Publish safely
• Locking can guarantee both: visibility and atomicity; volatile variables can only guarantee visibility.
References
• Goetz, Brian: Java Concurrency in Practice
• Bloch, Joshua: Effective Java
• Angelika Langer: Overview of the Java Memory Model
• Gosling, James et al.: The Java Language Specification, 3rd edition.
Modifying final fields
• Modification possible – Using reflection
– Triggers an immediate freeze
• Sometimes required– Executors,
– std{in,out,err} handlers
• Yet, discuraged– Require additional compiler knowledge
– Counter-intuitive
Outline
• Motivation
• Definitions
• JMM in a Nutshell
• The final Keyword
• Best Practices
• Diving in…
• Conclusions
Best Pratices
• Locking is not just about mutual exclusion; it is also about memory visibility. To ensure that all thread see the most up-to-date values of shared mutable variables, the reading and writing threads must synchronise on the same lock.
• Locking can guarantee both visibility and atomicity; volatile variables can only guarantee visibility.
Diving In…