Design Patterns & Concurrency Sebastian Graf, Oliver Haase 1 - PowerPoint PPT Presentation
Design Patterns & Concurrency Sebastian Graf, Oliver Haase 1 Expectations ? ...on the concurrency-part... 2 Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV.
Design Patterns & Concurrency Sebastian Graf, Oliver Haase 1
Expectations ? ...on the concurrency-part... 2
Outline of the concurrency part I. Fundamentals II. Concurrent Applications III. Liveness, Performance and Hazards IV. Advanced T opics All mapped on object-oriented programming with Java. 3
Why? 4
Why? ‣ More responsive programs due to less blocking ‣ Exploiting multi-processor architectures ‣ T ask-oriented working (e.g. like in Servlets, RMI) ‣ Simply handling of asynchronous events 5
Threads are everywhere ‣ Garbage Collection ‣ RMI Invocation (marshalling / unmarshalling) ‣ Servlets Importance of thread-safety is crucial! 6
Threadsafe ? public class Sequence { private int value; /** Returns a unique value. */ public int getNext() { return value++; } } 7
Thread-Unsafe ! 8
Threadsafe Impl. @ThreadSafe public class Sequence { @GuardedBy("this") private int nextValue; public synchronized int getNext() { return nextValue++; } } 9
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. 10
Simple Example public class StatelessFactorizer implements Servlet { public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); encodeIntoResponse(resp, factors); } } 11
State variable example public 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); } } 12
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); } } 13
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); } } } 14
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); } } } 15
Poor concurrency 16
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 17
Amdahl's law in detail ‣ P: Parts to be parallized ‣ 1-P: Part not to be parallized ‣ N: Number of Threads 18
Scaling of Amdahl's Law 19
One better solution public 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); } } 20
Fix broken code ‣ Do not share state variables across threads ‣ Make sate variables immutable ‣ Synchronizing access to shared state variables 21
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 22
Finally 23
Recommend
More recommend
Explore More Topics
Stay informed with curated content and fresh updates.