Synchronization 1
Overview synchronization mechanisms in modern RTEs concurrency issues places where synchronization is needed structural ways (design patterns) for exclusive access 2
Overview synchronization mechanism in Java RTE Visibility and re-ordering Design patterns to avoid safety issues: monitor pattern. client side locking. class composition. version iterattor. 3
Java Synchronization - concurrent objects safety threads which access the same object concurrently. safety - synchronize access to internal state of the object 4
class Even 5
if threads can access internal state of object concurrently - not safe @invariant is not guaranteed code perfectly safe in sequential environment 6
Visibility and Reordering unsafe constructs in concurrent execution Visibility - when threads see values written to memory by other threads Reordering - compiler / RTE change code to optimize it 7
8
anonymous class - class that has no name combines class declaration and instance creation in one step in-line allows "on the fly" creation of object reduce the number of.java files necessary class used in specific situation: Comparator compiler will create separate class files: ClassName$SomeNumber.class 9
Inlining 11
Inlining Inline expansion - compiler optimization that replaces a function call site with the body of the callee. improve time and space usage at runtime, at cost of binary file size 12
13
output = 0 thread t does not "see" the change to the state of d performed in main thread thread main - implicitly created by JVM executes main() method main calls d.set(10): 10 is written to memory: i_ member of: VisibilityDemo object t reads from i_ (d.get() ) Java does not guarantee t sees most recent value written to this memory location 14
Re-ordering compiler must be able to re-order simple instructions to optimize our code 15
Re-ordering compiler guarantees safe reordering in nonconcurrent execution environments. order of operations is that the sequence will end with operation 4 16
Re-ordering in concurrent environments, reordering may harm 17
must-happen-before compiler would not reorder if "must-happenbefore" constraint 18
must-happen-before "must-happen-before - call to any (noninline) function compiler would not go recursively into that function 19
"synchronized" construct in Java allow only one thread at a time to enter a specific method of an object synchronized keyword to method's declaration 20
synchronized Java coordinates actions of threads on object: keyword before method name in class definition: public synchronized int add() - only one thread is allowed to enter constructors cannot be synchronized - syntax error (only thread that creates an object access its constructor) 21
synchronized Java RTE ensures that only one thread access this method. solves visibility and reordering problems; "write" to memory during synchronized code section is guaranteed to be returned to all "read" operations following it 22
How "synchronized" is implemented? Java mechanism - use it better / avoid common pitfalls each object inside JVM (at runtime) has a lock ("monitor") JVM maintain/initialize locks. cannot access locks explicitly access implicitly using synchronized 23
locks locks are in one of two states; 1. in possession of thread 2. available thread T tries to acquire the lock of any object. if available lock transferred to T possession otherwise, T sleeps (queue) until lock available T wakes up and tries to acquire lock 24
synchronized each thread, calling the method, must first acquire lock. when thread exits thread releases lock 25
The cost of locks time, concurrency memory sync.: after thread exits memory of all threads synchronize with main memory thread may cache copies of memory in its own memory (e.g., CPU registers / CPU cache) blocking: threads must wait for each other 26
When to Use Synchronization mutable variable accessible from different threads must be protected with lock else, you may be hit by re-ordering problems monitor pattern - internal state of object is encapsulated. objects are responsible to synchronize access to state: synchronized get() /set() 27
When to Use Synchronization invariant involving several members - synchronized with same lock. never lock large parts of code. minimize code sections which use locking 28
Synchronized Properties synchronized keyword is not part of the method signature. synchronized keyword cannot be specified in an interface. constructors cannot be synchronized no point - as long as constructor is not complete, object instance is not accessible to other threads, unless static method as synchronized - lock associated with the class to be used (each class in Java is also an object on its own) Java locks are Reentrant: same thread holding the lock can get it again and again. 29
Statics Access to static fields protected via synchronized static methods and blocks. Static synchronization employs the lock possessed by the Class object static lock for class C can also be accessed inside instance methods via: synchronized(c.class) { /* body */ } 30
Locks are Reentrant 31
Locks are Reentrant/Recursive thread, T, acquired the lock of Even object in add(), T will be able to enter dosomething() - T already possesses lock of same object. 32
synchronized instance methods in subclasses employ the same lock as in their superclasses synchronization in an inner class method is independent of its outer class 33
Locks are Reentrant/Recursive Reentrant locks are implemented using counter same thread may acquire lock multiple time, consecutively, without releasing each time the lock is acquired, an internal counter is incremented. lock is unavailable whenever counter > 1. when thread releases the lock, the counter value is decremented by 1. when counter reaches 0, the lock is then available 34
Locking a Specific Object synchronized keyword to method declaration implicitly uses the lock of current object explicitly request to lock a specific object we wish to acquire not advised to use synchronized blocks. It is usually better to define synchronized methods 35
36
Vector: addifabsent() addifabsent() new class Vector hold some information javadoc - Vector class is thread-safe add an element only if missing Is it thread safe? 37
Not thread safe 38
Another solution? 39
incorrect solution lock protecting addifabsent() may be different from lock protecting add() not sure that add() is synchronized implementation of Vector may change - Vector can become not thread safe 40
Design Patterns to Enforce Safety Composition / Client Side Locking 41
Composition / Containment "almost" reimplementing the functionality of Vector. Why not extend Vector class and add the function we want? do not know how the class Vector protects itself from concurrent access. do not know/not have access to, which objects are used for synchronized access good design strategy to have a basic (non thread safe) object and a thread safe version of it. 42
Composition / Containment wrapper around Vector class: Enforces right synchronization policy Delegates all calls (after synchronization is verified) to underlying implementation class. 43
44
Composition / Containment we know exactly which lock is used to synchronize access to our vector. best applied in situations where: we are not sure/ do not know the internal implementation of an object implementation of object may change without our knowledge 45
all methods are synchronized. no public fields or encapsulation violations. methods are finite (no infinite loops or unbounded recursion) all fields are initialized to a consistent state in constructors. state of object is consistent 46
Client Side Locking we may know the identity of the object which is used for synchronization Vector class uses its own monitor (lock) to achieve synchronization 47
Client side locking only when we know internal implementation Vector uses monitor not when unknown internal implementation not when implementation may change 48
Client side locking not OO: responsibility of synchronization to clients instead of centralizing it in object cannot ensure consistency among ALL clients : If client does not synchronize correctly, then ALL the code will behave incorrectly. better to enforce safety on provider side 49
Version Iterators Iterators and Generics casting is bad - introduces clutter programmer knows what kind of data run time error if wrong cast 50
Generics programmers express intent restrict a list to contain a particular data type 51
List, Iterator interfaces (java.util) 52
Type parameters <T> <> - declarations of type parameters for List and Iterator interfaces used in declaration, instead ordinary types when used with actual type <Integer> all occurrences of formal type parameter <E> are replaced by Integer 53
Version iterators process Vector of Integers one at a time 54
Concurrency problem consider vec_ is shared by several threads, adding/removing elements concurrently. element pointed by iterator is deleted? new element is added at the beginning? 55
Solution synchronize loop synchronize iteration on vector body of loop may be arbitrarily long - locking the entire vector for the entire loop no access to object used to synchronize 56
Solution - immutable create a temporary copy of vector local to current thread iterate over copy inappropriate to copy the entire data structure need to lock the vector during copy operation, if vector class does not offer a thread-safe cloning 57
Solution - fail-fast Vector iterators are fail-fast: if element is added/removed after iterator was created except through Iterator's remove or add ConcurrentModificationException is thrown. 58
Solution - fail-fast useful for many readers few writers model fail-fast in java is on best-effort basis. fail-fast behavior of iterators in Java should be used only to detect bugs. 59
Version iterators Idea: maintain version number that is incremented upon each update to collection. iterator check value whenever asked for next element and throw exception if changed implementation of fail-fast iterators 60
61
Code-block synchronized version 62
Synchronized methods and blocks synchronized void f() { /* body */ } is equivalent to: void f() { synchronized(this) { /* body */ } } 63
More Synchronization Primitives Lock interface test that a lock can be acquired without blocking trylock() - returns if lock is not available Lock objects work like the implicit locks used when accessing a synchronized code segment. Only one thread can own a Lock object at a time. Semaphore Exchanger Latch 64