1 / 12

Review: Monitor Semantics

Review: Monitor Semantics. If P does X.wait() and later Q does X.signal(): Hoare Semantics: Q blocks yielding the monitor immediately to P Mesa Semantics: Q continues. P becomes runnable. P will eventually run, but only after Q exits Brinch Hanson:

merle
Download Presentation

Review: Monitor Semantics

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Review: Monitor Semantics • If P does X.wait() and later Q does X.signal(): • Hoare Semantics: • Q blocks yielding the monitor immediately to P • Mesa Semantics: • Q continues. P becomes runnable. P will eventually run, but only after Q exits • Brinch Hanson: • Q can only signal as it exits, so P will run next. • Java synchrnoized methodsj: • Only one reason to wait can exist. Notify() (the Java equivalent of signal() ) makes the blocked thread runnable as with Mesa semantics – it will run at a later time, after Q exits the monitor.

  2. Mesa vs. Hoare • MONITOR prod-con { • struct something buffer[n]; • int in=0, out=0; • int count=0; • condition=full, empty; • entry void add_item(data) { • /* Mesa semantics require a while – why? Bounded wait? */ • if/while (count==n) full.wait(); • buffer[in] = data; • in = (in + 1) % n; • count++; • empty.signal(); • } • /* continued */

  3. Mesa vs. Hoare (cont.) • /* continued */ • entry remove_item (data_ptr) • { • /* Mesa semantics require a while – why? Bounded wait? */ • if/while (count == n) empty.wait(); • *data_ptr = buffer[out]; • out = (out + 1) % n; • count--; • full.signal(); • }

  4. Dining philosophers • Rules • Philosophers alternate between thinking and eating • 2 chopsticks are required to eat • Philosophers never grab with both hands – they reach for one chopstick at a time. • A philosopher is too polite to steal a chopstick from a colleague • The philosophers cannot be allowed to starve • More than one philosopher should be able to eat at a time (no token ring!) P1 P0 Rice P2 P4 P3

  5. Dining Philosophers: Approach 1 • #define left(i) (i) • #define right(i) ((i-1) % 5) • MONITOR fork { • int avail[5] = {2, 2, 2, 2, 2 }; /* forks available to each phil */ • condition hungry[5]; • entry pickup_fork (int phil) { • if (avail[i] != 2) ready[i].wait(); • avail[left(I)]--; avail[right(I)]--; • } • entry putdown_fork (int phil) { • avail[left(i)]++: avail[right(i)]++; • if (avail[left(i)] == 2) ready[left(i).signal(); • if (avail[right(i)] == 2) ready[right(i)].signal(); • } • }

  6. Why Starvation? • Each philosopher is waiting for a different condition, so we can’t ensure fairness. • The solution is simple: all philosophers should wait for the same condition, such as their turn in a common queue.

  7. Dining Philosophers: Approach 2 • Semaphore chopstick[5] = { 1, 1, 1, 1, 1 }; • while (1) • { • P(chopstick[i]); • P(chopstick[(i+1) % 5]); • <<< eat >>> • V(chopstick[i]); • V(chopstick[(i +1) % 5]); • <<< think >>> • }

  8. What is Deadlock? • First, let’s define a resource: • Resources are an abstraction of any reason to wait. • Resources come in different types and we can have different numbers of each type. • A process/thread can acquire a resource, use it, and then fee it. • In this context, resources are unshareable – they are serially reusable. • Now let’s formally define deadlock: • The condition that arises when there exists a set of processes (or threads) such that each process holds a resource that another process in the set is waiting to acquire. The situation forces all processes in the set to wait forever.

  9. Why Deadlock? • Deadlock can occur if these conditions are satisfied: • Mutual exclusion – at least one resource must be held by a process. • Hold and wait – at least one process hold a resource while it is waiting for another resource. • No preemption – one process can’t take another process’s resources in order to make progress (nor can the OS) • Circular wait – there exists a circular chain of processes, each of which is waiting for a resource held by the next process in the chain.

  10. Simple Defense: Serialization • One simple defense against deadlock is to serialize the request of resources. • Enumerate all of the resources, giving each a number. • Require that all processes request resources in the order of this enumeration. That is to say that they are designed so that they never request a resource with a lower number than the highest numbered resource that they hold • Circular wait is now impossible, because the chain of waiting cannot wrap around from the greatest back to the beginning. It will eventually unfold.

  11. Dining philosophers - Serialized • Trace • P0 grabs Chopstick0, blocking P4 • P1 grabs Chopstick1, blocking P0 • P2 grabs Chopstick2, blocking P1 • P3 grabs Chopstick3, blocking P2 • P4 blocks trying to grab Chopstick0 • P3 is free to grab Chopstick4 • P3 can eat! P1 P0 1 2 Rice 0 P2 3 P4 4 P3

  12. Dining Philosophers: Approach 3 • Semaphore chopstick[5] = { 1, 1, 1, 1, 1 }; • while (1) • { • if (i < ((i+1) % 5)) { • P(chopstick[i]); • P(chopstick[(i+1) % 5]); • } else { • P(chopstick[(i+1) % 5]); • P (chopstick[i]); • } • <<< eat >>> • V(chopstick[i]); • V(chopstick[(i +1) % 5]); • <<< think >>> • }

More Related