Dining Philosophers - PowerPoint PPT Presentation

1 / 17
About This Presentation
Title:

Dining Philosophers

Description:

P0 P3 take the right chopsticks first (C0 to C3) ... Since there are 5 chopsticks in the room, actuall it is possible to have 2 ... – PowerPoint PPT presentation

Number of Views:729
Avg rating:3.0/5.0
Slides: 18
Provided by: andreaarpa
Category:

less

Transcript and Presenter's Notes

Title: Dining Philosophers


1
Dining Philosophers Monitors
UNIVERSITY of WISCONSIN-MADISONComputer Sciences
Department
CS 537Introduction to Operating Systems
Andrea C. Arpaci-DusseauRemzi H.
Arpaci-Dusseau Haryadi S. Gunawi
  • Questions answered in this lecture
  • How to synchronize dining philosophers?
  • What are monitors and condition variables?
  • What are the differences between Hoare and Mesa
    specifications?

2
Dining Philosophers
  • Problem Definitions
  • N Philosophers sitting at a round table
  • Each philosopher shares a chopstick with neighbor
  • Each philosopher must have both chopsticks to eat
  • Neighbors cant eat simultaneously
  • Philosophers alternate between thinking and
    eating
  • Each philosopher/thread i runs following code
  • while (1)
  • think()
  • take_chopsticks(i)
  • eat()
  • put_chopsticks(i)

3
Dining Philosophers Attempt 1
  • Two neighbors cant use chopstick at same time
  • Must test if chopstick is there and grab it
    atomically
  • Represent each chopstick with a semaphore
  • Grab right chopstick then left chopstick
  • Code for 5 philosophers
  • sem_t c 5 // c for chopstick
  • // Initialize each to 1
  • take_chopsticks(int i)
  • wait(ci) // take chopstick on your
    right
  • wait(c(i1)5) // take chopstick on your left
  • put_chopsticks(int i)
  • signal(ci) // put chopstick on your
    right
  • signal(c(i1)5) // put chopstick on your
    left
  • What is wrong with this solution? Deadlock!
  • Everyone picks up the left chopstick first

4
Dining Philosophers Attempt 2
  • Approach
  • Grab lower-numbered chopstick first, then
    higher-numbered
  • Code for 5 philosophers
  • take_chopsticks(int i)
  • if (i lt 4)
  • wait(ci) // take the right chopstick
    first
  • wait(ci1) //
  • else
  • wait(c0) // take the left chopstick first
  • wait(c4)
  • What is wrong with this solution? Not parallel
    enough!
  • P0 P3 take the right chopsticks first (C0 to
    C3)
  • P4 cannot take the left chopstick (C0) because P0
    already takes C0
  • That implies P4 cannot take C4, which implies C4
    can be taken by P3
  • Result only 1 process (P3) can eat but the other
    4 processes are waiting!
  • Since there are 5 chopsticks in the room, actuall
    it is possible to have 2 processes eat at the
    same time!

5
Dining Philosophers How to Approach
  • Guarantee two goals
  • Safety Ensure nothing bad happens (dont violate
    constraints of problem)
  • Liveness Ensure something good happens when it
    can (make as much progress as possible)
  • Introduce state variable for each philosopher i
  • statei THINKING, HUNGRY, or EATING
  • Safety No two adjacent philosophers eat
    simultaneously
  • for all i !(stateiEATING
    statei15EATING)
  • Liveness Not the case that a philosopher is
    hungry and his neighbors are not eating
  • for all i !(stateiHUNGRY
    (statei45!EATING statei15!EATING))

6
Dining Philosophers Solution
  • sem_t mayEat5 // how to initialize?
  • sem_t mutex // how to init?
  • int state5 THINKING
  • take_chopsticks(int i)
  • wait(mutex) // enter critical section
  • statei HUNGRY
  • testSafetyAndLiveness(i) // check if I can run
  • signal(mutex) // exit critical section
  • wait(mayEati)
  • put_chopsticks(int i)
  • wait(mutex) // enter critical section
  • statei THINKING
  • test(i1 5) // check if neighbor can run now
  • test(i4 5)
  • signal(mutex) // exit critical section
  • testSafetyAndLiveness(int i)
  • if (stateiHUNGRY statei45!EATINGsta
    tei15!EATING)

7
Recap Semaphore and Synchronization problems
  • Two Classes of Synchronization Problems
  • Uniform resource usage with simple scheduling
    constraints
  • No other variables needed to express
    relationships
  • Use one semaphore for every constraint
  • Examples thread join and producer/consumer
  • Complex patterns of resource usage
  • Cannot capture relationships with only semaphores
  • Need extra state variables to record information
  • Use semaphores such that
  • One is for mutual exclusion around state
    variables
  • One for each class of waiting
  • Examples readers/writers, and dining
    philosophers
  • Always try to cast problems into first, easier
    type

8
Locks/Semaphores Not Convenient
  • Problems
  • Must initialize semaphore properly
  • Last time semaphore can be set to 0, 1, or N
  • Misordering of locks/semaphores can be a problem
  • func1() wait(a) wait(b) . / do job /
    signal(b) signal(a)
  • func2() wait(b) wait(a) . / do job /
    signal(a) signal(b)
  • Deadlock!
  • Users can inadvertently misuse locks and
    semaphores
  • Ex forget to call signal(a) after wait(a)
  • Solution
  • Build another higher-level software primitive
    Monitors

9
Monitors
  • Idea
  • 1st part Provide language support to
    automatically lock and unlock monitor lock when
    in critical section
  • Lock is added implicitly never seen by user
  • 2nd part Provide condition variables for
    scheduling constraints
  • Examples
  • Mesa language from Xerox
  • Java from Sun
  • Use synchronized keyword when defining method
  • synchronized deposit(int amount)
  • balance amount

10
Example
With semaphore
With monitor
  • Monitor ProducerConsumer
  • doProduce()
  • // produce an item
  • doConsume()
  • // consume an item
  • void producer()
  • while(1)
  • doProduce()
  • void consumer()
  • while(1)
  • doConsume()
  • void producer()
  • while(1)
  • wait(mutex)
  • // produce an item
  • signal(mutex)
  • void consumer()
  • while(1)
  • wait(mutex)
  • // remove an item
  • signal(mutex)
  • What if buffer is empty/full?
  • Produce needs to wait if buffer is full
  • Consumer needs to wait if buffer is empty
  • Dont want to use semaphore, so we need new
    mechanism contidion variables

11
Condition Variables
  • Idea
  • Used to specify scheduling constraints
  • Always used with a monitor lock
  • No value (history) associated with condition
    variable
  • Allocate Cannot initialize value!
  • Must allocate a monitor lock too (implicit with
    language support, explicit in POSIX and C)
  • Three operations on a condition variable
  • wait(cv)
  • Call with monitor lock held Releases monitor
    lock Sleeps until signalled Reacquires lock
    when woken
  • Hence, for each cv, the monitor keeps a queue
  • NOTE (unlike semaphores wait(sem), there is no
    test in monitors wait(cv).
  • In monitor, when you call wait(cv), you will
    always go to sleep!
  • In semaphore, it depends on the semaphore value!

12
Condition Variables
  • signal(cv) or notify(cv)
  • Call with monitor lock held
  • Wake one thread waiting on this condition
    variable (if any)
  • If no thread is waiting, signal is discarded
  • NOTE no history (unlike semaphore value)
  • broadcast(cv) (or NotifyAll)
  • Wake all threads waiting on condition variable

13
Using condition variables
void producer() while(1)
doProduce() void consumer() while(1)
doConsume()
Monitor ProducerConsumer condition full,
empty doProduce() if (n10)
wait(full) // put an element (n) if
(n1) signal(empty) doConsume()
if (n0) wait(empty) // remove an
element (n--) if (n9) signal(full)

Note n and n-- implicitly protected by the
monitor lock. Hence, no need to add mutex
semaphore to guard n
14
Implementation of Signals Hoare vs. Mesa
  • Hoare (signal-and-exit)
  • Signaller relinquishes the CPU and gives the lock
    to the waiter
  • Problem
  • If sharing is between processes, context-switch
    too often!
  • Signaller might have something more todo
  • Complex to implement (signal() must be the last
    instruction)
  • Mesa (signal-and-continue)
  • Signaller can keep lock and CPU (Practice)
  • Easy to implement
  • But, the state that a thread is waiting on may
    not be true when the awaken process!

15
Hoare/Mesa
Monitor ProducerConsumer condition full,
empty doProduce() a acquire(lock) b
if (n10) c wait(full) d // put an
element e if (n1) f signal(empty) g
// do other stuffs h release(lock)
doConsume() s acquire(lock) t if
(n0) u wait(empty) v // remove an
element w if (n9) x signal(full) y
// do other stuffs z release(lock)
Hoare 2s 2t 2u 1a 1b 1d 1e 1f 2v 2w
Mesa 2s 2t 2u 1a 1b 1d 1e 1f 1g 1h 2v
2w The idea is at 1f, process 2 is removed from
the wait queue. After 1h ends, even the OS does
not guarantee that 2v will run directly. Whats
the problem? What will happen in this
scenario Mesa (1 producer, 2 consumers) 2s 2t
2u 1a 1b 1d 1e 1f 1g 1h 3s 3t 3u 3v 3w 3x 3y 3z
2v 2w Thread3 (a consumer) already consumes the
item that thread1 produces! When thread2 is at
2v, there is no item to work on!
16
Mesa
Monitor ProducerConsumer condition full,
empty doProduce() a acquire(lock) b
while (n10) c wait(full) d // put an
element e if (n1) f signal(empty) g
// do other stuffs h release(lock)
doConsume() s acquire(lock) t while
(n0) u wait(empty) v // remove an
element w if (n9) x signal(full) y
// do other stuffs z release(lock)
  • Mesa
  • A process is waiting/sleeping because of a
    condition (e.g. producer sleeps because n 0)
  • When a process is awaken up, that condition might
    not be true anymore
  • Hence, need to put a while loop!
  • while ( no resource )
  • wait (cv)
  • Mesa (1 producer, 2 consumers)
  • 2s 2t 2u 1a 1b 1d 1e 1f 1g 1h 3s 3t 3u 3v 3w 3x
    3y 3z 2t ltsleepgt
  • Hence thread 2 cannot proceed again.

17
Summary
  • Locks
  • Mutual exclusion only
  • Semaphore
  • Mutual exclusion
  • Scheduling
  • Good for scheduling
  • Bad error prone if used for locking
    (initialization, ordering)
  • Monitors
  • Good for mutual exclusion (implicit) and
    scheduling
Write a Comment
User Comments (0)
About PowerShow.com