design patterns & concurrency · 3 outline of the concurrency part i. fundamentals ii....

23
Sebastian Graf, Oliver Haase 1 Design Patterns & Concurrency

Upload: others

Post on 20-Jun-2020

21 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

Sebastian Graf, Oliver Haase

1

Design Patterns & Concurrency

Page 2: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

2

Expectations ?

...on the concurrency-part...

Page 3: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

3

Outlineof the concurrency part

I. Fundamentals

II. Concurrent Applications

III. Liveness, Performance and Hazards

IV. Advanced Topics

All mapped on object-oriented programming with Java.

Page 4: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

4

Why?

Page 5: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

5

Why?

‣More responsive programs due to less blocking

‣Exploiting multi-processor architectures

‣Task-oriented working (e.g. like in Servlets, RMI)

‣Simply handling of asynchronous events

Page 6: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

6

Threads are everywhere

‣Garbage Collection

‣RMI Invocation (marshalling / unmarshalling)

‣Servlets

Importance of thread-safety is crucial!

Page 7: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

7

Threadsafe ?public class Sequence {

private int value;

/** Returns a unique value. */

public int getNext() {

return value++;

}

}

Page 8: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

8

Thread-Unsafe !

Page 9: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

9

Threadsafe Impl.@ThreadSafe

public class Sequence {

@GuardedBy("this") private int nextValue;

public synchronized int getNext() {

return nextValue++;

}

}

Page 10: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

10

Definition of Threadsafety

Managing access to state, in particular to shared, mutable state (directly to member-variables of one class) with

‣Atomic change of state

‣ Invariants, Pre- /Postconditions

‣…

Providing any necessary synchronization so that the client needs no own one.

Page 11: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

11

Simple Examplepublic class StatelessFactorizer implements Servlet {

public void service(ServletRequest req, ServletResponse resp) {

BigInteger i = extractFromRequest(req);

BigInteger[] factors = factor(i);

encodeIntoResponse(resp, factors);

}

}

Page 12: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

12

State variable examplepublic class CountingFactorizer implements Servlet {

private long count = 0;

public long getCount() { return count; }

public void service(ServletRequest req, ServletResponse resp) {

BigInteger i = extractFromRequest(req);

BigInteger[] factors = factor(i);

++count;

encodeIntoResponse(resp, factors);

}

}

Page 13: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

13

Thread-safe state variable example

public class CountingFactorizer implements Servlet {

private final AtomicLong count = new AtomicLong(0);

public long getCount() { return count.get(); }

public void service(ServletRequest req, ServletResponse resp) {

BigInteger i = extractFromRequest(req);

BigInteger[] factors = factor(i);

count.incrementAndGet();

encodeIntoResponse(resp, factors);

}

}

Page 14: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

14

Next one...public class UnsafeCachingFactorizer implements Servlet {

private final AtomicReference<BigInteger> lastNumber

= new AtomicReference<BigInteger>();

private final AtomicReference<BigInteger[]> lastFactors

= new AtomicReference<BigInteger[]>();

public void service(ServletRequest req, ServletResponse resp) {

BigInteger i = extractFromRequest(req);

if (i.equals(lastNumber.get()))

encodeIntoResponse(resp, lastFactors.get() );

else {

BigInteger[] factors = factor(i);

lastNumber.set(i);

lastFactors.set(factors);

encodeIntoResponse(resp, factors);

}

}

}

Page 15: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

15

One Solution...public class SynchronizedFactorizer implements Servlet {

@GuardedBy("this") private BigInteger lastNumber;

@GuardedBy("this") private BigInteger[] lastFactors;

public synchronized void service(ServletRequest req,

ServletResponse resp) {

BigInteger i = extractFromRequest(req);

if (i.equals(lastNumber))

encodeIntoResponse(resp, lastFactors);

else {

BigInteger[] factors = factor(i);

lastNumber = i;

lastFactors = factors;

encodeIntoResponse(resp, factors);

}

}

}

Page 16: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

16

Poor concurrency

Page 17: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

17

Excursion, Amdahl's Law

“For the past thirty years, computer performance has been driven by Moore’s Law; from now on, it will be driven by Amdahl’s Law. [...]”

-- Doron Rajwan, Research Scientist, Intel Corp

Page 18: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

18

Amdahl's law in detail

‣P: Parts to be parallized

‣1-P: Part not to be parallized

‣N: Number of Threads

Page 19: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

19

Scaling of Amdahl's Law

Page 20: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

20

One better solutionpublic class CachedFactorizer implements Servlet {

@GuardedBy("this") private BigInteger lastNumber;

@GuardedBy("this") private BigInteger[] lastFactors;

@GuardedBy("this") private long hits;

@GuardedBy("this") private long cacheHits;

public synchronized long getHits() { return hits; }

public synchronized double getCacheHitRatio() {

return (double) cacheHits / (double) hits; }

public void service(ServletRequest req, ServletResponse resp) {

BigInteger i = extractFromRequest(req);

BigInteger[] factors = null;

synchronized (this) {

++hits;

if (i.equals(lastNumber)) {

++cacheHits;

factors = lastFactors.clone();

}

}

if (factors == null) {

factors = factor(i);

synchronized (this) {

lastNumber = i;

lastFactors = factors.clone();

}

}

encodeIntoResponse(resp, factors);

}

}

Page 21: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

21

Fix broken code

‣Do not share state variables across threads

‣Make sate variables immutable

‣Synchronizing access to shared state variables

Page 22: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

22

But...

‣Do not serialize heavy computations

‣Remember Amdahl's law

‣Think about what needs to be parallized from the point of view of program correctness

Page 23: Design Patterns & Concurrency · 3 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced Topics All mapped

23

Finally