260 likes | 275 Views
COMP 111. Threads and concurrency Sept 28, 2005. Who is this guy?. I am not Prof. Couch Obvious? Sam Guyer New assistant professor in CS Complete Ph.D. in 2003 at University of Texas Grew up in Boston Research area: Compilers Mostly, new applications and algorithms. My research.
E N D
COMP 111 Threads and concurrency Sept 28, 2005
Who is this guy? • I am not Prof. Couch Obvious? • Sam Guyer • New assistant professor in CS • Complete Ph.D. in 2003 at University of Texas • Grew up in Boston • Research area: Compilers Mostly, new applications and algorithms
My research • Compilers are powerful tools • Performance improvement • Through program transformation • Better cooperation with run-time system, OS • Error checking • Analyze program behavior • Try to predict errors – eg, null pointer dereference • Try to identify security holes – eg, buffer overrun This problem is wicked hard
Today: Threads • What are they? • Why use ‘em? • Problems – synchronization • Wait, why are we using them? • Off to Dr. Couch’s OneNote presentation…
Why use threads? • Hide latency • Don’t wait for disk access, network transfers, etc • Less overhead than processes • Easier for threads to cooperate than processes • Schedule on multiprocessors • True parallelism • Near future: all processors will have multiple cores • Great, threads are easy, right? • Not so fast…
Synchronization – Motivation • “The too much milk problem” • Example of need to synchronize activities Thanks to Emery Berger UMass Amherst
Increment the value of x by one Example • Consider following routine: int x = 0; void *threaded_routine (void * v) { const int *n = (int *)v; int i; for (i=0; i<10; i++) { int y=x; y++; printf("%d: y=%d\n",*n,y); sleep(1); x=y; printf("%d: x=%d\n",*n,x); } }
Multithreaded • Run three instances • Should produce “30” – three threads increment the value 10 times • How can we fix this?
Solving the Too Much Milk Problem • Correctness properties • Only one person buys milk • Safety: “nothing bad happens” • Someone buys milk if you need to • Progress: “something good eventually happens” • Add some synchronization protocol: • “Leave a note” (lock) • “Remove a note” (unlock) • “Don’t buy milk if there’s a note” (wait)
Too Much Milk: Solution 1 thread A if (no milk && no note) leave note buy milk remove note thread B if (no milk && no note) leave note buy milk remove note too much milk • Does this work?
Too Much Milk: Solution 2 thread A leave note A if (no note B) if (no milk) buy milk remove note A Idea: use labeled notes thread B leave note B if (no note A) if (no milk) buy milk remove note B oops – no milk
Too Much Milk: Solution 3 thread A leave note A while (note B) do nothing if (no milk) buy milk remove note A Idea: wait for the right note thread B leave note B if (no note A) if (no milk) buy milk remove note B • Must try all possibilities to verify
Too Much Milk: Solution 3 thread A leave note A while (note B) do nothing if (no milk) buy milk remove note A Possibility 1: A first, then B thread B leave note B if (no note A) if (no milk) buy milk remove note B • OK
Too Much Milk: Solution 3 Possibility 2: B first, then A thread A leave note A while (note B) do nothing if (no milk) buy milk remove note A thread B leave note B if (no note A) if (no milk) buy milk remove note B • OK
Too Much Milk: Solution 3 thread A leave note A while (note B) do nothing if (no milk) buy milk remove note A Possibility 3: Interleaved – A waits & buys thread B leave note B if (no note A) if (no milk) buy milk remove note B • OK
Too Much Milk: Solution 3 Possibility 4: Interleaved – A waits, B buys thread A leave note A while (note B) do nothing if (no milk) buy milk remove note A thread B leave note B if (no note A) if (no milk) buy milk remove note B • OK
Too Much Milk: Solution 3 Solution 3:“Thread A waits for B, otherwise buys” • Correct – preserves desired properties • Safety: we only buy one milk • Progress: we always buy milk • But…
Problems with this Solution • Complicated • Difficult to convince ourselves that it works • Asymmetrical • Threads A & B are different • Adding more threads = different code for each thread • Poor utilization • Busy waiting – consumes CPU resources, no useful work • Possibly non-portable • Relies on atomicity of loads & stores
Synchronization Terminology Mutual exclusion (“mutex”)– prevents multiple threads from entering Critical section– code only one thread can execute at a time Race condition– outcome of some code is non-deterministic Lock– mechanism for mutual exclusion Atomic or atomicity– either all completes, or none completes
Locks • Provide mutual exclusion to shared data via two atomic routines • Lock::Acquire – wait for lock, then take it • Lock::Release – unlock, wake up waiters • Rules: • Acquire lock before accessing shared data • Release lock afterwards • Lock – initially released
Too Much Milk: Locks thread A Lock.acquire() if (no milk) buy milk Lock.release() thread B Lock.acquire() if (no milk) buy milk Lock.release()
With locks… int x=0; void *threaded_routine (void * v) { const int *n = (int *)v; int i; for (i=0; i<10; i++) { pthread_mutex_lock(&locker); int y=x; y++; printf("%d: y=%d\n",*n,y); sleep(1); x=y; printf("%d: x=%d\n",*n,x); pthread_mutex_unlock(&locker); } }
Locks • Now run three threads… • What have we accomplished? Made the update of x atomic • Clean, symmetric - but how do we implement it?
Implementing Locks • Requires hardware support (in general) • Can build on atomic operations: • Load/Store • Disable interrupts • Uniprocessors only • Test & Set, Compare & Swap
Race conditions • In practice: These are the most difficult bugs you will ever see • Often occur intermittently • Debugging changes the timing, hides the bug • What to do? • Two neat-o approaches • Run-time race detection • Compile-time race detection
Summary • Communication between threads:via shared variables • Critical sections = regions of code that modify or access shared variables • Must be protected by synchronization primitives that ensure mutual exclusion • Loads & stores: tricky, error-prone • Solution: high-level primitives (e.g., locks)