Presentation is loading. Please wait.

Presentation is loading. Please wait.

Lecture 8 Thread Safety.

Similar presentations


Presentation on theme: "Lecture 8 Thread Safety."— Presentation transcript:

1 Lecture 8 Thread Safety

2 Concurrent Systems: Properties
Safety: Nothing unplanned ever happens to the values or expected results Correctness The system does what it was meant to Reusability The objects can be reused in several systems without changing code Liveness System advances in its execution of code Performance Intended activity eventually completes, and uses resources efficiently

3 Safety: Definition Nothing bad should ever happen to a shared object:
Objects should change only following the programmer intentions Multi-threaded safety: Problem: safety in concurrent systems cannot be checked at compile time! It requires both correct system design, and correct system implementation Designing concurrent systems that use resource sharing is difficult! Todays concurrent systems steer away from sharing resources! Alleviating concurrent systems safety issues: Can be done by applying conditions on classes Three kinds of conditions: pre-condition, post-condition, and invariant

4 Example: EvenCounter Class
/* A simple counter class, which keeps an even counter value */ class EvenCounter { /* the internal state counter */ private int counter = 0; /* default constructor */ public EvenCounter() { } int getCounter() { return counter; } int setCounter(int count) { counter = count; } /* increment the counter. * return the current counter value */ public int increment() { setCounter(getCounter() + 1); return getCounter(); } We wish to ensure the state consistency of a class instance, we ensure the consistency of the following: Object State: counter value must be even value at all times Operations: increment() counter

5 Class Conditions: Definitions
These are statements about the state of the object Pre <condition> Condition must hold before executing the method Post <condition> Condition must hold after the method finishes its execution <condition> These statements must hold throughout the lifetime of the object

6 Class EvenCounter: Conditions
What is a possible pre-condition on increment()? In what state the object is in before executing this method? Counter value is even! What is a possible post-condition on increment()? In what state the object will be in after executing this method? Counter value is even What will happen to object state once we finish executing this method? Counter has been incremented What are possible invariant conditions on the state of the object? Internal counter always remains even Counter value might change during actions on or by the object

7 EvenCounter Example: Adding Conditions
/* A simple counter class, which keeps an even counter */ class EvenCounter { /* the internal state counter counter % 2 = 0 */ private int counter = 0; /* default constructor */ public EvenCounter() { } int getCounter() { return counter; } int setCounter(int counter) { this.counter = counter; } /* increment the counter. * return the updated counter value getCounter() % 2 = 0 (this is redundant, as it is promised by * public int add() { setCounter(getCounter() + 1); return getCounter(); }

8 Consistency and computation
We introduced the pre/post and inv conditions to define: “an object is in consistent state”. Only the object can update its own internal state. Construction: after the constructor holds.

9 Consistency and computation
Each time a method is called: @pre condition should be checked. After the method finishes computing: @post condition should be checked. Definition: The safety condition for a system’s run is that all object conditions are held - as viewed from the perspective of each object.

10 Consistency and computation
While a method is executing, there is no constraint that remains enforced. Example: add()method in EvenCounter.

11 Thread Safety: EventCounter Example
/* a simple class which has a reference to an EvenCounter object. */ class Adder implements Runnable { /* the reference to an EvenCounter Object */ private EvenCounter evenCounter; /* simple constructor evenCounter a reference to an EvenCounter object */ public Adder(EvenCounter evenCounter) { this.evenCounter= evenCounter; } /* increment the counter 10 times*/ public void run() { for (int i=0; i<10; i++) System.out.println(evenCounter.increment()); } public static void main(String[] args) { // Note: a single Even instance is shared by 2 Adder instances. EvenCounter evenCounter = new EvenCounter(); Thread t1 = new Thread(new Adder(evenCounter)); Thread t2 = new Thread(new Adder(evenCounter)); t1.start(); t2.start(); Two threads, each one incrementing the same object 10 times, we expect 40 with increments of two for each increment() execusion Expected result?

12 …EvenCounter class is not thread safe
run:  …EvenCounter class is not thread safe

13 Dangers of Concurrent Execution
Code correctness? all computations involving this code are correct. In sequential RTE: analyze each method. check all potential execution paths. make hold in the concurrent execution model?

14 Investigation At some point in each thread's execution, the thread is preempted by the environment in favor of another thread. The preemption may take place any time during the execution of the thread. add()  - performs many more actions than you can see…

15 Investigation pseudo JVM code:
execution of any thread may be interrupted at any line…

16 Investigation Run: After this run: (before the print()) counter = 5!
After this run: (before the print()) counter = 5!

17 Repair? Unfortunately, a thread can be interrupted before line 3.

18 interleaving of execution
Assume counter_ = 2 at time t0 T1 executes line 1 and is interrupted. (c == 2 holds) T2 executes line 1 and is interrupted. (c == 2 holds) T1 executes lines 2 and 3 (c == 4 holds holds) T2 executes lines 2 and 3 (c == 4 holds holds)

19 Interleaving of execution
Same object - shared between 2 threads (T1, T2) Object executes the method add() twice – state of the object is incremented only once. Local constraints never failed. T1 thinks all is fine. T2 thinks all is fine. Your bank account is wrong!!! "something wrong happened" but our formal tools cannot tell us what.

20 Reasons behind EvenCounter failure
increment()is not an atomic operation Atomic operations are those that preemption does not affect them More: counter = counter + 2 is also not an atomic operation! This combination of reasons breaks our enforced conditions: The code can be preempted Incrementing the counter is not an atomic operation If we have a look locally on each thread The conditions and code are correct! However, globally the code does not enforce the condition!

21 Computation Correctness: Global Criterion
The concurrent execution of a program is correct iff: conditions hold throughout the execution Linearizability of the computation Linearizability: Final state of objects: They are in states that could have been reached by a sequential execution Sequence of states: They can be reached, for each object, by a sequential execution Then, the concurrent code can be converted to a sequential one And executed correctly!

22 Example: abstract computation system
Sequences transitions from object perspective: O1: S11 --m1()--> S12 --m2()--> S13 O2: S21 --n1()--> S22 Now consider this example: an abstract computation system involves 2 objects O1 and O2. From the perspective of each object, the computation involves these sequences of transitions:

23 Example: Linearizability
Sequential model RTE: 3 transitions ordered relative to each other into a single execution If no dependency between executions: We can have all possible interleaving: S11 S12 S13 S21 S22 S11 S12 S21 S13 S22 S11 S12 S21 S22 S13 S11 S21 S12 S22 S13 S11 S21 S22 S12 S13 S21 S11 S22 S12 S13 S21 S22 S11 S12 S13

24 Dependency: n1() is called by O1 during the execution of m2()
O1: S11 --m1()--> S12 --m2()--> S13 O2: S21 --n1()--> S22 Additional ordering constraint  S22 > S12 S11 S12 S13 S21 S22 S11 S12 S21 S13 S22 S11 S12 S21 S22 S13 S11 S21 S12 S22 S13 less possible total orderings in the sequential execution

25 Safety in concurrent RTEs:
Any mechanism that we will introduce will: Impose serialization constraints among independent transitions

26 Safe Concurrent Programming Ingredients
Immutability - avoiding state changes. Using this method we avoiding state changes Shared objects are read only No need for exclusive access! The object cannot enter inconsistent states! one thread at a time can access object state, by protecting objects with locks and related constructs.

27 Safe Concurrent Programming Ingredients
Synchronization - dynamically ensuring exclusive access Ensuring that only one thread at a time can access object states, or critical sections of the code. Done by protecting objects with locks and related constructs. Shared objects are accessed sequentially in these critical sections one thread at a time can access object state, by protecting objects with locks and related constructs.

28 Safe Concurrent Programming Ingredients
Containment - Structurally ensuring exclusive access Structurally ensure exclusive access of objects This is done by using design patterns Does not allow concurrent access – only sequential one thread at a time can access object state, by protecting objects with locks and related constructs.

29 Immutability Definition: If an object cannot change state
Immutable object  - cannot be modified after it is created Mutable object - can be modified after it is created If an object cannot change state Then it can never encounter inconsistencies due to concurrent access! Simplest solution for thread safety – in terms of coding No thread may change the internal state of the object Cheap to do at design stage However, code change will require refactoring large parts of code - expensive

30 immutable EvenCounter
new object of EvenCounter - its internal state may not change - ever object is always safe, even in concurrent execution environments.

31 Creating Immutable Classes
No setter methods - such as setX() All fields final and private Immutable instances are always initialized during construction. No method overriding can be done by doing one of the following: Class declared final, or Constructor made private and object construction is done in factory methods. If the member variables include references to mutable objects: Ensure no methods that modify the mutable objects References to the mutable objects are not to be shared or returned. References to external mutable objects passed to the constructor are read only. Copies of internal mutable objects can be returned, never the original variables.

32 Immutable EvenCounter
/* A counter class, which keeps an even counter */ class EvenCounter { /* the internal state counter - it is changed to final counter % 2 = 0 */ private final int counter; /* private default constructor */ private EvenCounter() { counter = 0; } /* factory method – creates instances of EvenCounter*/ public static EvenCounter create() { return new EvenCounter(); } /* a private constructor c % 2 = 0 private EvenCounter(int counter) { this.counter = counter; } /* increment the counter. * return a new Object counter % 2 = 0 (this is redundant, as it is promised by * * public EvenCounter increment() { return new EvenCounter(counter+2); } }

33 Reminder: Static methods  - use no instance variables of any object of the class they are defined in. cannot access any instance variables. ONLY static variables.

34 Incrementor and the Main function
class Incrementor implements Runnable{ private EvenCounter evenCounter; public Incrementer(EvenCounter evenCounter){ this.evenCounter = evenCounter; } public void run(){ for (int i=0;i<10;i++){ evenCounter = evenCounter.increment(); public int getValue(){ return evenCounter.getValue(); class RunConcurrentCode{ public static void main(String[] args){ Incrementor incrementor1 = new Incrementor(EvenCounter.create()); Incrementor incrementor2 = new Incrementor (EvenCounter.create()); Thread t1 = new Thread(incrementor1); Thread t2 = new Thread(incrementor2); t1.start(); t2.start(); try{ t1.join(); t2.join(); } catch(InterruptedException e){ } int value = incrementor1.getValue() + incrementor2.getValue(); System.out.print(value); } 40, yes Output? Everytime?

35 Immutable objects are applicable when:
Object serves as instances of a simple abstract data type representing values. For example: colors, numbers, strings. different classes supporting different usage can be designed, one immutable and the another updatable. java.lang.String is immutable java.lang.StringBuffer is updatable.

36 Immutable objects are applicable when:
benefit of safe object outweighs cost of copying object each time it changes Copying technique is popular and is valid. trade-off: readability and execution time Java does not support pass-by-copy for non-scalar types. copy by another assignment. In some RTE (not Java though), the actual copying may be delayed to the moment a change occur to the variable, thus saving execution time in some scenarios. multiple objects representing the same values (for a reason not related to safety).

37 Stateless methods Another aspect of immutability are stateless methods. A stateless method is a method that does not change the object state. provide services

38 Immutable “Wrapper”

39 Immutable “Wrapper” Note that the previous example is weak.
The server inner fields can be modified even though it is final (either in relay or outside of it). Only the reference field “server” cannot be modified. Modifications: Either server is created inside relay and is not exposed outside. Relay only expose certain methods of server, that do not change the server’s state.


Download ppt "Lecture 8 Thread Safety."

Similar presentations


Ads by Google