CPS110: Thread cooperation

Slides:



Advertisements
Similar presentations
Operating Systems Semaphores II
Advertisements

Process Synchronization A set of concurrent/parallel processes/tasks can be disjoint or cooperating (or competing) With cooperating and competing processes.
PROCESS SYNCHRONIZATION READINGS: CHAPTER 5. ISSUES IN COOPERING PROCESSES AND THREADS – DATA SHARING Shared Memory Two or more processes share a part.
Chapter 6: Process Synchronization
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
1 Mutual Exclusion: Primitives and Implementation Considerations.
CPS110: Implementing threads/locks on a uni-processor Landon Cox.
U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts, Amherst Operating Systems CMPSCI 377 Lecture.
Synchronization CSCI 444/544 Operating Systems Fall 2008.
Synchronization Andy Wang Operating Systems COP 4610 / CGS 5765.
Concurrency Recitation – 2/24 Nisarg Raval Slides by Prof. Landon Cox.
1 Lecture 9: Synchronization  concurrency examples and the need for synchronization  definition of mutual exclusion (MX)  programming solutions for.
1 Thread Synchronization: Too Much Milk. 2 Implementing Critical Sections in Software Hard The following example will demonstrate the difficulty of providing.
Pthread (continue) General pthread program structure –Encapsulate parallel parts (can be almost the whole program) in functions. –Use function arguments.
CS510 Concurrent Systems Introduction to Concurrency.
Object Oriented Analysis & Design SDL Threads. Contents 2  Processes  Thread Concepts  Creating threads  Critical sections  Synchronizing threads.
COMP 111 Threads and concurrency Sept 28, Tufts University Computer Science2 Who is this guy? I am not Prof. Couch Obvious? Sam Guyer New assistant.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Mutual Exclusion.
11/18/20151 Operating Systems Design (CS 423) Elsa L Gunter 2112 SC, UIUC Based on slides by Roy Campbell, Sam.
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science Software Systems Advanced Synchronization Emery Berger and Mark Corner University.
CS399 New Beginnings Jonathan Walpole. 2 Concurrent Programming & Synchronization Primitives.
CSCI-375 Operating Systems Lecture Note: Many slides and/or pictures in the following are adapted from: slides ©2005 Silberschatz, Galvin, and Gagne Some.
1 Condition Variables CS 241 Prof. Brighten Godfrey March 16, 2012 University of Illinois.
COSC 3407: Operating Systems Lecture 9: Readers-Writers and Language Support for Synchronization.
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science Computer Systems Principles Synchronization Emery Berger and Mark Corner University.
CPS110: Thread cooperation Landon Cox. Constraining concurrency  Synchronization  Controlling thread interleavings  Some events are independent  No.
1 Previous Lecture Overview  semaphores provide the first high-level synchronization abstraction that is possible to implement efficiently in OS. This.
Review: threads and processes Landon Cox January 20, 2016.
Implementing Lock. From the Previous Lecture  The “too much milk” example shows that writing concurrent programs directly with load and store instructions.
1 Critical Section Problem CIS 450 Winter 2003 Professor Jinhua Guo.
CS510 Concurrent Systems Jonathan Walpole. Introduction to Concurrency.
Slides on threads borrowed by Chase Landon Cox. Thread states BlockedReady Running Thread is scheduled Thread is Pre-empted (or yields) Thread calls Lock.
Concurrency: Locks and synchronization Slides by Prof. Cox.
Implementing Mutual Exclusion Andy Wang Operating Systems COP 4610 / CGS 5765.
CPS110: Implementing threads on a uni-processor Landon Cox January 29, 2008.
CS162 Section 2. True/False A thread needs to own a semaphore, meaning the thread has called semaphore.P(), before it can call semaphore.V() False: Any.
Lecture 5 Page 1 CS 111 Summer 2013 Bounded Buffers A higher level abstraction than shared domains or simple messages But not quite as high level as RPC.
6/27/20161 Operating Systems Design (CS 423) Elsa L Gunter 2112 SC, UIUC Based on slides by Roy Campbell, Sam King,
29 June 2015 Charles Reiss CS162: Operating Systems and Systems Programming Lecture 5: Basic Scheduling + Synchronization.
Review Array Array Elements Accessing array elements
CPS110: Reader-writer locks
CS703 – Advanced Operating Systems
Background on the need for Synchronization
COMPSCI210 Recitation 12 Oct 2012 Vamsi Thummala
Atomic Operations in Hardware
Atomic Operations in Hardware
Review: threads and synchronization
CSCI 511 Operating Systems Chapter 5 (Part A) Process Synchronization
CSCI 511 Operating Systems Chapter 5 (Part A) Process Synchronization
Synchronization Lecture 23 – Fall 2017.
Andy Wang Operating Systems COP 4610 / CGS 5765
Race conditions and Synchronization
Implementing Mutual Exclusion
Slides by Prof. Landon Cox and Vamsi Thummala
Implementing Mutual Exclusion
CSE 451: Operating Systems Autumn 2004 Module 6 Synchronization
CSE 451: Operating Systems Autumn 2003 Lecture 7 Synchronization
CSE 451: Operating Systems Autumn 2005 Lecture 7 Synchronization
CSE 451: Operating Systems Winter 2003 Lecture 7 Synchronization
CSE 153 Design of Operating Systems Winter 19
CSE 153 Design of Operating Systems Winter 2019
CS333 Intro to Operating Systems
Chapter 6: Synchronization Tools
CSE 451 Section 1/27/2000.
CS 144 Advanced C++ Programming May 7 Class Meeting
“The Little Book on Semaphores” Allen B. Downey
EECE.4810/EECE.5730 Operating Systems
EECE.4810/EECE.5730 Operating Systems
Don Porter Portions courtesy Emmett Witchel
Don Porter Portions courtesy Emmett Witchel
Presentation transcript:

CPS110: Thread cooperation Landon Cox January14, 2009

Project 0 void main () { // create a new list Dlist<foo> *list = new Dlist<foo> (); // insert a new object list->insertFront (new foo ()); // remove and delete the object delete list->removeFront (); // insert another object // delete the list delete list; } How much memory should be allocated here? How much memory should be allocated here?

Constraining concurrency Some events are independent No shared state Relative order of these events “don’t matter” Other events are dependent Output of one can be input to another Their order can affect program results Not all orders/schedules/interleavings are correct Synchronization Controlling thread interleavings

Another example Two threads (A and B) A tries to increment i B tries to decrement i Thread A: i = o; while (i < 10){ i++; } print “A done.” Thread B: i = o; while (i > -10){ i--; } print “B done.”

Example continued Who wins? Does someone have to win? Thread A: i = o; while (i < 10){ i++; } print “A done.” Thread B: i = o; while (i > -10){ i--; } print “B done.”

Example continued Thread A: Thread B: Will it go on forever if both threads Start at about the same time And execute at exactly the same speed? Yes, if each C statement is atomic. Thread A: i = o; while (i < 10){ i++; } print “A done.” Thread B: i = o; while (i > -10){ i--; } print “B done.”

Example continued What if i++/i-- are not atomic? tmp := i+1 i := tmp (tmp is private to A and B)

Example continued Thread A: tmpA := i + 1 // tmpA == 1 Non-atomic i++/i-- If A starts ½ statement ahead, B can win How? Thread A: tmpA := i + 1 // tmpA == 1 Thread B: tmpB := i - 1 // tmpB == -1 Thread A: i := tmpA // i == 1 Thread B: i := tmpB // i == -1

Goals of synchronization All interleavings must give correct result Correct concurrent program Works no matter how fast threads run Important for your projects! Constrain program as little as possible Constraints slow program down Constraints create complexity

“Too much milk” principals

“Too much milk” rules The fridge must be stocked with milk Milk expires quickly, so never > 1 milk Landon and Melissa Can come home at any time If either sees an empty fridge, must buy milk Code (no synchronization) if (noMilk){ buy milk; }

Unsynchronized code will break Time 3:00 Look in fridge (no milk) 3:05 Go to grocery store 3:10 3:15 Buy milk 3:20 3:25 Arrive home, stock fridge 3:30 3:35 Too much milk!

What broke? Code worked sometimes, but not always Code contained a race condition Processor speed caused incorrect result First type of synchronization Mutual exclusion Critical sections

Synchronization concepts Mutual exclusion Ensure 1 thread doing something at a time E.g. 1 person shops at a time Code blocks are atomic w/re to each other Threads can’t run code blocks at same time

Synchronization concepts Critical section Code block that must run atomically “with respect to some other pieces of code” If A and B are critical w/re to each other Threads mustn’t interleave events in A and B A and B mutually exclude each other Often conflicting code is same block But executed by different threads Reads/writes shared data (e.g. screen, fridge)

Back to “Too much milk” What is the critical section? Landon and Melissa’s critical sections Must be atomic w/re to each other if (noMilk){ buy milk; }

“Too much milk” solution 1 Assume only atomic load/store Build larger atomic section from load/store Idea: Leave notes to say you’re taking care of it Don’t check milk if there is a note

Solution 1 code Atomic operations Atomic load: check note Atomic store: leave note if (noMilk) { if (noNote){ leave note; buy milk; remove note; }

Does it work? 1 2 3 4 if (noMilk) { if (noNote){ leave note; buy milk; remove note; } if (noMilk) { if (noNote){ leave note; buy milk; remove note; } 1 2 3 4 Is this better than no synchronization at all? What if “if” sections are switched?

What broke? Melissa’s events can happen After Landon checks for a note Before Landon leaves a note if (noMilk) { if (noNote){ leave note; buy milk; remove note; }

Next solution Idea: Change the order of “leave note”, “check note” Requires labeled notes (else you’ll see your note)

Does it work? Nope. (Illustration of “starvation.”) leave noteLandon if (no noteMelissa){ if (noMilk){ buy milk; } remove noteLandon leave noteMelissa if (no noteLandon){ if (noMilk){ buy milk; } remove noteMelissa Nope. (Illustration of “starvation.”)

What about now? Nope. (Same starvation problem as before) while (noMilk){ leave noteLandon if(no noteMelissa){ if(noMilk){ buy milk; } remove noteLandon while (noMilk){ leave noteMelissa if(no noteLandon){ if(noMilk){ buy milk; } remove noteMelissa Nope. (Same starvation problem as before)

Next solution We’re getting closer Problem Solution Who buys milk if both leave notes? Solution Let Landon hang around to make sure job is done

Does it work? Yes! It does work! Can you show it? leave noteLandon while (noteMelissa){ do nothing } if (noMilk){ buy milk; remove noteLandon leave noteMelissa if (no noteLandon){ if (noMilk){ buy milk; } remove noteMelissa Yes! It does work! Can you show it?

Downside of solution Note: only needed atomic load/store Complexity Hard to convince yourself it works Asymmetric Landon and Melissa run different code Not clear if this scales to > 2 people Landon consumes CPU while waiting Busy-waiting Note: only needed atomic load/store

Raising the level of abstraction Mutual exclusion with atomic load/store Painful to program Wastes resources Need more HW support Will be covered later OS can provide higher level abstractions

Course administration Project 1 (two parts) Write a small concurrent program Implement a thread library (single CPU) Create new threads Switch between threads Manage interactions btw cooperating threads Out on Wednesday, should be able to start E.g. disk scheduler input routine

Too much milk solution leave noteLandon while (noteMelissa){ do nothing } if (noMilk){ buy milk; remove noteLandon leave noteMelissa if (no noteLandon){ if (noMilk){ buy milk; } remove noteMelissa

Downside of solution Note: only needed atomic load/store Complexity Hard to convince yourself it works Asymmetric Landon and Melissa run different code Not clear if this scales to > 2 people Landon consumes CPU while waiting Busy-waiting Note: only needed atomic load/store

Raising the level of abstraction Locks Also called mutexes Provide mutual exclusion Prevent threads from entering a critical section Lock operations Lock (aka Lock::acquire) Unlock (aka Lock::release)

Lock operations Lock: wait until lock is free, then acquire it This is a busy-waiting implementation We’ll improve on this in a few lectures Unlock: atomic release lock do { if (lock is free) { acquire lock break } } while (1) Must be atomic with respect to other threads calling this code

Too much milk, solution 2 Why doesn’t the note work as a lock? if (noMilk) { if (noNote){ leave note; buy milk; remove note; } Block is not atomic. Must atomically check if lock is free grab it Why doesn’t the note work as a lock?

Elements of locking Key idea Threads are either running or blocked The lock is initially free Threads acquire lock before an action Threads release lock when action completes Lock() must wait if someone else has lock Key idea All synchronization involves waiting Threads are either running or blocked

Too much milk with locks? Problem? Waiting for lock while other buys milk lock () if (noMilk) { buy milk } unlock () lock () if (noMilk) { buy milk } unlock ()

Too much milk “w/o waiting”? lock () if (noNote && noMilk){ leave note “at store” unlock () buy milk remove note } else { } lock () if (noNote && noMilk){ leave note “at store” unlock () buy milk remove note } else { } Not holding lock Only hold lock while handling shared resource.

What about this? 2 1 4 3 lock () if (noMilk && noNote){ leave note “at store” unlock () buy milk stock fridge remove note } else { } lock () if (noMilk lock () if (noMilk && noNote){ leave note “at store” unlock () buy milk stock fridge remove note } else { } 2 1 4 3

Example: thread-safe queue enqueue () { lock (qLock) // ptr is private // head is shared node *ptr; // find queue tail for (ptr=head; ptr->next!=NULL; ptr=ptr->next){} ptr->next=new_element; new_element->next=0; unlock(qLock); } dequeue () { lock (qLock); element=NULL; // if queue non-empty if (head->next!=0) { // remove head element=head->next; head->next=head->next->next; } unlock (qLock); return element; What can go wrong?

Thread-safe queue Can enqueue unlock anywhere? Must leave shared data No Must leave shared data In a consistent/sane state Data invariant “consistent/sane state” “always” true enqueue () { lock (qLock) node *ptr; for (ptr=head; ptr->next!=NULL; ptr=ptr->next){} ptr->next=new_element; unlock(qLock); // safe? new_element->next=0; }

Invariants What are the queue invariants? Each node appears once (from head to null) Enqueue results in prior list + new element Dequeue removes exactly one element Can invariants ever be false? Must be Otherwise you could never change states

More on invariants So when is the invariant broken? Can only be broken while lock is held And only by thread holding the lock Really a “public” invariant What is the data’s state in when the lock is free Like having a room tidy before guests arrive Hold a lock whenever manipulating shared data

More on invariants What about reading shared data? Still must hold lock Else another thread could break invariant (Thread A prints Q as Thread B enqueues)

How about this? I’m always holding a lock while accessing shared state. enqueue () { lock (qLock) node *ptr; for (ptr=head; ptr->next!=NULL; ptr=ptr->next){} unlock (qLock); lock (qLock); ptr->next=new_element; new_element->next=0; unlock(qLock); } ptr may not point to tail after lock/unlock. Lesson: Thinking about individual accesses is not enough Must reason about dependencies between accesses

What about Java? Too much milk Every object is a lock Use synchronized key word Lock : “{“, unlock: “}” synchronized (obj){ if (noMilk) { buy milk } synchronized (obj){ if (noMilk) { buy milk }

Synchronizing methods public class CubbyHole { private int contents; public int get() { return contents; } public synchronized void put(int value) { contents = value; What does this mean? What is the lock? “this” is the lock

Synchronizing methods public class CubbyHole { private int contents; public int get() { return contents; } public void put(int value) { synchronized (this) { contents = value; Equivalent to “synchronized (this)” block

Next class Mutual exclusion is great and all, but Ordering constraints Is not really expressive enough Ordering constraints Often must wait for something to happen Use something called “monitors”