Date post: | 17-Jan-2016 |
Category: |
Documents |
Upload: | dominic-pierce |
View: | 225 times |
Download: | 0 times |
SPL/2010SPL/2010
Synchronization
1
SPL/2010SPL/2010
Overview
● synchronization mechanisms in modern RTEs
● concurrency issues● places where synchronization is needed
● structural ways (design patterns) for exclusive access
2
SPL/2010SPL/2010
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
SPL/2010SPL/2010
Java Synchronization - concurrent objects safety
● threads which access the same object concurrently.
● safety - synchronize access to internal state of the object
4
SPL/2010SPL/2010
class Even
5
SPL/2010SPL/2010
● if threads can access internal state of object concurrently - not safe● @invariant is not guaranteed● code perfectly safe in sequential environment
6
SPL/2010SPL/2010
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
SPL/2010SPL/2010 8
SPL/2010SPL/2010
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
SPL/2010SPL/2010
Inlining
11
SPL/2010SPL/2010
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
SPL/2010SPL/2010 13
SPL/2010SPL/2010
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
SPL/2010SPL/2010
Re-ordering
● compiler must be able to re-order simple instructions to optimize our code
15
SPL/2010SPL/2010
Re-ordering
● compiler guarantees safe reordering in non-concurrent execution environments.
● order of operations is that the sequence will end with operation 4
16
SPL/2010SPL/2010
Re-ordering
● in concurrent environments, reordering may harm
17
SPL/2010SPL/2010
“must-happen-before”
● compiler would not reorder if "must-happen-before" constraint
18
SPL/2010SPL/2010
“must-happen-before”
● "must-happen-before“ - call to any (non-inline) function ● compiler would not go recursively into that
function
19
SPL/2010SPL/2010
"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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
synchronized
● each thread, calling the method, must first acquire lock.
● when thread exits – thread releases lock
25
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
Locks are Reentrant
31
SPL/2010SPL/2010
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
SPL/2010SPL/2010
● 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
SPL/2010SPL/2010
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
available34
SPL/2010SPL/2010
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
SPL/2010SPL/2010 36
SPL/2010SPL/2010
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
SPL/2010SPL/2010
Not thread safe
38
SPL/2010SPL/2010
Another solution?
39
SPL/2010SPL/2010
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
SPL/2010SPL/2010
Design Patterns to Enforce Safety
● Composition / Client Side Locking
41
SPL/2010SPL/2010
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
SPL/2010SPL/2010
Composition / Containment
● wrapper around Vector class:● Enforces right synchronization policy● Delegates all calls (after synchronization is
verified) to underlying implementation class.
43
SPL/2010SPL/2010 44
SPL/2010SPL/2010
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
SPL/2010SPL/2010
● 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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
Client side locking
● only when we know internal implementation ● Vector uses monitor
● not when unknown internal implementation
● not when implementation may change
48
SPL/2010SPL/2010
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
SPL/2010SPL/2010
Version Iterators
● Iterators and Generics
● casting is bad - introduces clutter ● programmer knows what kind of data ● run time error – if wrong cast
50
SPL/2010SPL/2010
Generics
● programmers express intent ● restrict a list to contain a particular data type
51
SPL/2010SPL/2010
List, Iterator interfaces (java.util)
52
SPL/2010SPL/2010
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
SPL/2010SPL/2010
Version iterators
● process Vector of Integers one at a time
54
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010
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
SPL/2010SPL/2010 61
SPL/2010SPL/2010 62
Code-block synchronized version
SPL/2010SPL/2010
Synchronized methods and blocks
synchronized void f() { /* body */ }
is equivalent to:
void f() { synchronized(this) { /* body */ } }
63
SPL/2010SPL/2010
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