Published on

Introduction to concurrent programming concepts

Published in: Technology, Education
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide


  1. 1. ConcurrentProgramming May 6, 2010
  2. 2. Agenda• Motivational Examples• Computing Model• Race Conditions• Deadlocks• Resources 2
  3. 3. Sleeping Barber “BAU” Process Barber cuts hair When finished, he checks the waiting room If no one is there, he goes to sleep in the chair Customers arriving while the barber is asleep wake the barber What can go wrong? Barber finishes, walks to waiting room Customer arrives and goes to wake the barber They do not see each other, return and wait indefinitely 3
  4. 4. Dining Philosophers “BAU” Process Philosophers alternate between thinking and eating Two forks are required to eat spaghetti When finished thinking, philosophers seek forks When finished eating, philosophers put forks down What can go wrong? Process of picking up, putting down forks can result in each philosopher holding one fork - none can eat Dining Philosophers Demo 4
  5. 5. Computing Canonical Model • Processes spawn threads to do work • Threads maintain local state but can also access shared state • Threads can be active, suspended, blocked waiting for resources or sleeping • Threads execute concurrently - truly concurrently in multi-processor environments, virtually concurrently in single- processor environments • Thread scheduling is managed by the parent process, operating system and / or application • Sequencing of operations across different threads is in general unpredictableShared State 5
  6. 6. Simple Computing Problem Bad Timing Web App Hit Counter • Multi-threaded web app wants to maintain a count of the number of hits it gets Read counter • Shared state is used to maintain the count • Request processing threads update the count each time they process a request • Under heavy load, the app seems to “miss” Read counter some hits. Why? Assign counter+1 public void increment() { Assign counter+1 count = count + 1; }Badness results from B reading the counter while A is in process of updating it. This is an example of arace condition. 6
  7. 7. Solution Semaphore Keep B out while A updates • Could make “count++” operation atomic (i.e. unable to be interrupted.) The JDK 1.5 AtomicInteger class does this. Close the door • More general solution is to synchronize access to the shared resource • Using a semaphore, Thread A signals exclusive access to the critical section of code that does the update Knock on door • Simplest semaphore is a mutex (mutual exclusion - just one allowed in at a time) and simplest implementation Update, open door in Java is via the synchronized keyword Close door, update public synchronized void increment() { count = count + 1; }Note that the same solution would work for the sleeping barber (close door to waiting room) 7
  8. 8. Synchronized Keyword in Java • Acts as a mutex on blocks of code • Can protect entire methods, or blocks within methods • Uses the concept of a monitor on an object to represent the mutex - code entering a synchronized block acquires an object monitor • When no object is specified, the monitor on the object executing the code is implied • Synchronization locks are reentrant - i.e., if a thread owns an object’s monitor and it enters another method that requires the same monitor, it is allowed in • When a thread leaves a synchronized block, it releases the associated monitor (even if an exception occurs) Parent object’s monitor Fu’s monitorpublic synchronized void foo() { public void foo() { public void foo() {; synchronized (this) { synchronized (fu) {};; } } } } 8
  9. 9. Concurrent Object Access Method Object Threads Object ReferencesWhen multiple threads share references to the same object, they can concurrently call the samemethod on the object, unless synchronization prevents this. A class is thread-safe if concurrentlyexecuting threads can safely hold references to instances of the class. 9
  10. 10. Programmer’s Challenge: Situational Awareness • The question always needs to be asked, “will multiple threads hold references to instances of this class at the same time?” Unfortunately, it is sometimes hard to know. • Most common use cases involving concurrent access are created by application containers, often in conjunction with application frameworks. Containers manage threads and frameworks instantiate objects. Fun begins when the Singleton Pattern is used by the framework.Primitive Survival Technique: Avoid the bad neighborhood altogether• Keep is Stateless Stupid (KISS) - avoid maintaining state across method calls• Prefer immutable objects - only final fields, all set by constructors• Never spawn threads - let the container manage them• Use tested, thread-safe resource providers (e.g. databases) to maintain state (when you are dragged kicking and screaming into acknowledging the need to maintain state at all)• Encapsulate parameters needed by methods in value objects and pass these to/from methods instead of relying on instance fields 10
  11. 11. Anatomical Examplepublic class Foo { public static final int HOSIERY_THRESHOLD = 1000; No worries private boolean fubar; ... public void hose(int ways) { Careful! int newWays = generateNewWays(); if (ways + newWays > HOSIERY_THRESHOLD) { fubar = true; } }• Static final fields are initialized when the class is loaded and don’t change thereafter, so all threads see the same values - threadsafe• Method parameters are provided to each thread on the call stack and are only visible to that thread for the duration of the method - threadsafe• Local variables declared within methods are only visible to the thread activating the method for the duration of the method - threadsafe• Class member fields are visible to all threads, so if two threads can be inside a method that uses a member field at the same time, care must be taken to synchronize access 11
  12. 12. Example - Struts 1.x Actions Servlet Container 1. When the web app starts, it loads ActionServlet the Struts ActionServlet (one ActionServlet instance per web FooAction application - a singleton) BarAction 2. When the ActionServlet is initialized, it reads its configuration and loads one instance each of the Action classes defined in its configuration FubarAction (more singletons) 3. When browser requests arrive, the container assigns processing threads to requests and passes requests mapped to the Struts application to the Struts ActionServlet instance 4. The Struts ActionServlet calls perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) on the single Action instance that it uses for all requestsConsequence: Struts Action classes must be threadsafe!rtfm:// 12
  13. 13. Struts 1.x Example (Cont.)Inside a Struts Action Class:private String successPath = null;private String failedPath = null;private String maxAttemptsPath = null;public ActionForward perform( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException { // Set forward paths, using request information setForwardPaths(mapping, request ); ...Depending on processing outcome, forward to configured path}private void setForwardPaths(ActionMapping mapping, HttpServletRequest request) { ... successPath = ... failedPath = ... maxAttemptsPath = ...} Problem: If two requests for this action are processed concurrently, and the computed forward paths are different, control can be misdirected. 13
  14. 14. Struts 1.x Example - Fixprivate String successPath = null;private String failedPath = null;private String maxAttemptsPath = null;public ActionForward perform( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException { // Set forward paths, using request information ForwardPaths forwardPaths = getForwardPaths(mapping,request); String successPath = forwardPaths.getSuccessPath(); String failedPath = forwardPaths.getFailedPath(); String maxAttemptsPath = forwardPaths.getMaxAttemptsPath(); ...Depending on processing outcome, forward to configured path}private ForwardPaths setForwardPaths(ActionMapping mapping, HttpServletRequest request) { // Compute and store local variables success, failed, maxAttempt representing paths ... return new ForwardPaths(success, failed, maxAttempts);} Eliminating the member fields makes the class threadsafe. Introduction of a value object (ForwardPaths inner class not shown) enables data to be safely transmitted to/from the private helper method. 14
  15. 15. Deadlock Thread 1 Thread 2 Acquire lock A Acquire lock B Block waiting to acquire lock B Block waiting to acquire lock AThread 1 can’t proceed until it gets the lock that Thread 2 is holding on B. Thread 2 can’tproceed until it gets the lock that Thread 1 is holding on A. No other threads can do anythingthat requires either lock. This kind of situation can cause application servers to “hang.” 15
  16. 16. DeadLock ExampleApache Commons Pool provides Maintenance Thread Client Threada generic object pooling API andimplementationsApache Commons DBCP is a Acquire pool lockdatabase connection pool that Acquire factoryuses Commons Pool as its lockunderlying object pool Block waiting toWhen used together, versions acquire factory1.2-1.4 of Commons Pool and lock1.1-1.2.x of Commons DBCPcould create a deadlock (tracked Block waiting toas DBCP-44 in ASF JIRA) acquire pool lockSource of the deadlock:Contention between clientthreads borrowing / returning Resolution: Modify pool code to move allobjects and a maintenance thread invocations of factory methods outside offor locks on the pool and objects synchronized scope (so lock in 0 is released beforeused by the pool’s object factory step 2 is attempted) 16
  17. 17. Avoiding DeadlocksRule number 0: Leave concurrency management to external resource providers or fullytested frameworks - try to design around the need for synchronizationRule number 1: When holding a lock, never call any methods that require other locksWould completely eliminate possibility of deadlock; but unfortunately not always possibleRule number 2: When you must use multiple locks to perform actions in your application,establish a hierarchy of locks and always acquire locks in the order determined by thehierarchyRule number 3: Maintain a complete and consistent execution model of applicationsubsystems and make explicit (via both documentation and test cases) invariants that enforcelock hierarchy and/or prevent contention for locksRule number 4: Pay special attention to exception processing, especially when using explicitlocks (i.e., objects that implement the Lock interface) - make sure locks are released on allexecution paths 17
  18. 18. ResourcesJava Threads, Scott Oaks, Henry Wong ( Little Book of Semaphores, Allen B Downey (“Concurrent Programming with J2SE 1.5” ( Also read carefully the class javadoc for all of the classes in theconcurrency package“Hierarchical Ordering of Sequential Processes”, Edsker Dijkstra, working paper (“Sequential Programming vs Concurrent Programming”, Jerry Cain ( little “OT”:“On the Nature of Time - Why does Nature Abhor Deadlocks?”, Christine Cordula Dantas( 18