230 likes | 256 Views
Operating Systems CMPSCI 377 Lecture 8: Synchronization II. Emery Berger University of Massachusetts Amherst. Last Time: Synchronization. Threads communicate to ensure consistency If not: race condition (non-deterministic result) Accomplished by synchronization operations
E N D
Operating SystemsCMPSCI 377Lecture 8: Synchronization II Emery Berger University of Massachusetts Amherst
Last Time: Synchronization • Threads communicate to ensure consistency • If not: race condition(non-deterministic result) • Accomplished by synchronization operations • How to write concurrent code • How to implement synchronization operations
This Time: Locks & Semaphores • Implementing locks • Semaphores
Atomic Read-Write-Modify Instructions • Atomicallyread old value,write new value • SMP invalidates copies in other caches • Cache coherence support • Examples: • Test & Set (most arch) • Exchange (x86) • Compare & Swap (68K, Sparc)
Implementing Locks: Test & Set int testset (int value) { int old = value; value = 1; return old; } pseudo-code: red = atomic • What’s the effect of testset(value) when: • value = 0? • value = 1?
Implementing Locks: Test & Set int testset (int value) { int old = value; value = 1; return old; } class Lock { private int value; Lock() { value = 0; } void acquire() {…} void release() {…} } pseudo-code: red = atomic • acquire – wait until lock released, then take it • release – release lock void acquire() { while (testset(value)) {} } void release() { value = 0; }
Busy Waiting (“Spinning”) • What’s wrong with this implementation? • CPU utilization? • Different priorities? void acquire() { while (testset(value)) {} } void release() { value = 0; } spin-lock
Minimizing Busy Waiting • Can’t implement locks with test & set without any waiting (w/o disabling interrupts) • Add queue to lock and sleep: blocking lock void acquire() { while (1) { if (testset(value)) { put thread on queue, sleep } else { break; } } } void release() { value = 0; wake up threads; }
Locks as Synch Operations • Locks provide mutual exclusion • Only one thread enters section at a time • Simplifies writing concurrent programs • Low-level • Can complicate coding • e.g., “allow at most n threads to access resource” • What are some alternatives?
This Time: Locks & Semaphores • Implementing locks • Semaphores
Brief Segue:Edsger W. Dijkstra (1930-2002) • Shortest Path • First modern compiler (Algol-60) • Stack for implementing recursion, vector • First modular OS (THE) • Predicate transformers • On-the-fly garbage collection • Self-stabilizing systems • Mutual exclusionproblem: • “Deadly embrace”(now called deadlock) • Semaphores
Semaphores • What’s a “semaphore” anyway? A visual system for sending information by means of two flags that are held one in each hand, using an alphabetic code based on the position of the signaler's arms.
Semaphores • What’s a “semaphore” anyway? A visual signaling apparatus with flags, lights, or mechanically moving arms, as one used on a railroad.
Semaphores • What’s a “semaphore” anyway? A visual signaling apparatus with flags, lights, or mechanically moving arms, as one used on a railroad. • Intuitively: regulates traffic at critical section
Semaphores in CS • Computer science: Dijkstra (1965) A non-negative integer counter with atomic increment & decrement. Blocks rather than going negative. • Higher-level than locks but not too high level
Semaphores: Key Concepts • P(sem),a.k.a. wait = decrement counter • If sem = 0, block until greater than zero • P = “prolagen” (proberen te verlagen, “try to decrease”) • V(sem), a.k.a. signal = increment counter • Wake 1 waiting process • V = “verhogen” (“increase”) In Holland the good Dr. Dijkstra Took a break from a walk on his bijkstra And said: "Which shall it be? Take a P or a V? For the two seem to me quite alijkstra!"
Implementing Semaphores class Semaphore { private int value; private Queue q; Semaphore(int v) { value = v; } } void wait() { if (value > 0) { value = value – 1; } if (value == 0) { add this process to Q; sleep(); } } void signal() { value = value + 1; if (anyone on Q) { remove P from Q; wakeup(P); } }
Variants of Semaphores • Binary semaphore • just two values (0 or 1), initially 1 (“free”) • Counting semaphore • useful when units of resource are available • initialized to number of resources • thread can access as long as one unit available
Binary Semaphores: Example • “too much milk” with locks thread A Lock.acquire() if (no milk) buy milk Lock.release() thread B Lock.acquire() if (no milk) buy milk Lock.release() thread A sem.wait() if (no milk) buy milk sem.signal() thread B sem.wait() if (no milk) buy milk sem.signal() • “too much milk” with binary semaphores(initially 1)
Binary Semaphore: Example • More flexible than locks! • By initializing semaphore to 0,threads can wait for an event to occur thread A // wait for thread B sem.wait(); // do stuff … thread B // do stuff, then // wake up A sem.signal();
Counting Semaphores: Example • Controlling resources: • Allow threads to use at most 5 files simultaneously • Initialize to 5 thread A sem.wait(); // use a file sem.signal(); thread B sem.wait(); // use a file sem.signal();
Summary • Implementing locks • Test & Set • Spin locks, blocking locks • Semaphores • Generalization of locks • Binary, “Dijkstra-style” • Useful for: • Controlling resources • Waiting on events
Next Time • Synchronization III! • Monitors