Sharing Objects Synchronization Atomicity Specifying critical sections Memory visibility One thread’s modification seen by the other Visibility T1: X = 5; print(X); will result in 5. T1: X = 5; T2: print(X); may or may not print 5. Use synchronization
Example
Problems with the example Infinite loop ready not visible to ReaderThread Reordering Not detectable from within the thread Apparent to other threads Insufficiently synchronized multithreaded programs Reasoning on order of memory actions can be incorrect Stale data Not all-or-nothing Unexpected exceptions Corrupted data structures Inaccurate computations Infinite loops
Stale data – Example
Fixed example
Locking and visibility Use locking for visibility other than mutual exclusion
Volatile variables Weaker form of synchronization Updates propagated to other threads Ensures Variables are not cached in registers Not reordered with other memory operations Ensures visibility for other variables Not recommended however volatile boolean asleep; … while(!asleep) doSomething();
Volatile variables (contd.) volatile int x = 0; x++; Volatile variables Visibility Locking Visibility and atomicity
Publication and escape Object available to code outside current scope Storing a reference Returning from a non-private method Passing it to a method in another class Escape Publish when it should not have been public static Set knownSecrets; public void initialize() { knownSecrets = new HashSet (); }
Escape of internal mutable states Class UnsafeStates { private String[] states = …. public String[] getStates() { return states; } } Passing to alien methods
Safe construction practices Do not allow this to escape during construction Start thread from a constructor Incomplete object seen by thread Create but not start. Private constructor and public factory method
Thread confinement Ad-hoc thread confinement Implementation takes care of confinement Fragile Stack confinement Reachable through local variables See next slide for example Maintenance harder ThreadLocal (Language support) ThreadLocal approx. equals Map Port single-threaded application to multithreaded Same caution as with global variables
Example for stack confinement
Immutability Mutability Stale values, losing updates, inconsistent state Immutable State cannot be changed after construction Inherently thread-safe Reasoning about state of immutable objects – trivial Passable to untrusted code Definition (in Java) State cannot be modified after construction All fields are final Properly constructed (this does not escape)
Safe publication
Immutable objects and initialization safety Object reference becomes visible to another thread State of that object is not necessarily visible Synchronization is needed Immutable objects Synchronization not needed (in Java)
Safe publication idioms Reference to the object and object’s state made visible simultaneously Safe publication using Initializing object reference from a static initializer Class initialization time Storing reference to it into a volatile field (or AtomicReference) Storing reference into a final field Storing reference to a field that is properly guarded by a lock
Safe publication (contd.) Effectively immutable Not technically immutable State will not be modified after publication No need for synchronization Improve performance Publication requirements Immutable objects published via any mechanism Effectively immutable objects must be safely published Mutable objects – safely published and Guarded by a lock or Thread-safe
Sharing objects safely What to do with an object reference Acquire a lock before using it? Can state be modified? Is it read-only object? Policies for using and sharing objects Thread-confined Shared read-only Immutable and effectively immutable No addl. synchronization Shared thread-safe No addl. synchronization by user Guarded Accessed only with a specific lock