design patterns concurrency
play

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.


  1. Design Patterns & Concurrency Sebastian Graf, Oliver Haase 1

  2. Expectations ? ...on the concurrency-part... 2

  3. 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

  4. Why? 4

  5. 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

  6. Threads are everywhere ‣ Garbage Collection ‣ RMI Invocation (marshalling / unmarshalling) ‣ Servlets Importance of thread-safety is crucial! 6

  7. Threadsafe ? public class Sequence { private int value; /** Returns a unique value. */ public int getNext() { return value++; } } 7

  8. Thread-Unsafe ! 8

  9. Threadsafe Impl. @ThreadSafe public class Sequence { @GuardedBy("this") private int nextValue; public synchronized int getNext() { return nextValue++; } } 9

  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. 10

  11. 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

  12. 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

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

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

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

  16. Poor concurrency 16

  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 17

  18. Amdahl's law in detail ‣ P: Parts to be parallized ‣ 1-P: Part not to be parallized ‣ N: Number of Threads 18

  19. Scaling of Amdahl's Law 19

  20. 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

  21. Fix broken code ‣ Do not share state variables across threads ‣ Make sate variables immutable ‣ Synchronizing access to shared state variables 21

  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 22

  23. Finally 23

Recommend


More recommend