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

Post on 20-Jun-2020

11 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Sebastian Graf, Oliver Haase

1

Design Patterns & Concurrency

2

Expectations ?

...on the concurrency-part...

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.

4

Why?

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

6

Threads are everywhere

‣Garbage Collection

‣RMI Invocation (marshalling / unmarshalling)

‣Servlets

Importance of thread-safety is crucial!

7

Threadsafe ?public class Sequence {

private int value;

/** Returns a unique value. */

public int getNext() {

return value++;

}

}

8

Thread-Unsafe !

9

Threadsafe Impl.@ThreadSafe

public class Sequence {

@GuardedBy("this") private int nextValue;

public synchronized int getNext() {

return nextValue++;

}

}

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.

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);

}

}

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);

}

}

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);

}

}

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);

}

}

}

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);

}

}

}

16

Poor concurrency

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

18

Amdahl's law in detail

‣P: Parts to be parallized

‣1-P: Part not to be parallized

‣N: Number of Threads

19

Scaling of Amdahl's Law

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);

}

}

21

Fix broken code

‣Do not share state variables across threads

‣Make sate variables immutable

‣Synchronizing access to shared state variables

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

23

Finally

top related