



Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
The Dining Philosophers problem is a classic computer science problem that uses a metaphor of philosophers eating spaghetti to illustrate synchronization issues in concurrent systems. various algorithms to prevent starvation and deadlock in this context. The problem statement is provided, followed by an explanation of a simple but incorrect approach, and Tannenbaum's solution that maximizes concurrency. The document also touches upon deadlock and its conditions, as well as reactions to deadlock by an operating system.
Typology: Lecture notes
1 / 6
This page cannot be seen from the preview
Don't miss anything!




A Classic Problem - Dining Philosophers
The Dining Philosophers problem is a classic OS problem that’s usuallu stated in very non-OS terms: There are N philosphers sitting around a circular table eating spaghetti and discussing philos- phy. The problem is that each philosopher needs 2 forks to eat, and there are only N forks, one between each 2 philosophers. Design an algorithm that the philosophers can follow that insures that none starves as long as each philosopher eventually stops eating, and such that the maximum number of philosophers can eat at once. Why describe problems this way? Well, the analogous situations in computers are sometimes so technical that they obscure creative thought. Thinking about philosophers makes it easier to think abstractly. And many of the early students of this field were theoreticians who like abstract problems. There are a bunch of named problems - Dining Philosophers, Drinking Philiosophers, Byzantine Generals, etc.
Here’s an approach to the Dining Phils^1 that’s simple and wrong: void philosopher() { while(1) { sleep(); get_left_fork(); get_right_fork(); eat(); put_left_fork(); put_right_fork(); } }
If every philosopher picks up the left fork at the same time, noone gets to eat - ever.
Some other suboptimal alternatives:
(^1) Now that you’ve seen the problem, you can call them Phil, too.
#define N 5 /* Number of philosphers */ #define RIGHT(i) (((i)+1) %N) #define LEFT(i) (((i)==N)? 0 : (i)+1)
typedef enum { THINKING, HUNGRY, EATING } phil_state;
phil_state state[N]; semaphore mutex =1; semaphore s[N]; /* one per philosopher, all 0 */
void test(int i) { if ( state[i] == HUNGRY && state[LEFT(i)] != EATING && state[RIGHT(i)] != EATING ) {state[i] = EATING; V(s[i]);} }
void get_forks(int i) { P(mutex); state[i] = HUNGRY; test(i); V(mutex); P(s[i]); }
void put_forks(int i) { P(mutex); state[i]= THINKING; test(LEFT(i)); test(RIGHT(i)); V(mutex); }
void philosopher(int process) { while(1) { think(); get_forks(process); eat(); put_forks(process); } }
The magic is in the test routine. When a philosopher is hungry it uses test to try to eat. If test fails, it wiats on a semaphore until some other process sets its state to EATING. Whenever a philosopher puts down forks, it invokes test in its neighbors. (Note that test does nothing if the process is not hun- gry, and that mutual exclusion prevents races.)
So this code is correct, but somewhat obscure. And more importantly, it doesn’t encapsulate the philosopher - philosophers manipulate the state of their neighbors directly. Here’s a version that does not require a process to write another process’s state, and gets equivalent parallelism.
#define N 100 /* Number of free slots */
semaphore mutex = 1; semaphore empty = N; semaphore full = 0;
void producer() { item i;
while (1) { i = produce_item(); P(mutex); P(empty); insert_new_item(i); V(mutex); V(full); } }
void consumer() { item i;
while(1) { P(full); P(mutex); i = get_next_item(); V(mutex); V(empty); consume_item(i); } }
When the producer arrives at a full queue, it will block on empty while holding mutex, and the consumer will subsequently block on mutex forever. Graphically, this looks like:
Process a
Resource 1
Process b
Resource 2
Wants
Wants
Has
Has
Processes we hopefully understand. Resources are the other parts of the computer system - hardware and software. For the purposes of deadlock, we’re concerned with resources that require exclusive control: tape drives, CD-ROM burners, locks & semaphores, process table slots, etc.
4 Conditions
More formally there are 4 conditions for deadlock:
Requesting a resource
Holding a resource
All four conditions are can be expressed in the graph:
A Deadlock Example
Consider a set of processes making the following requests: A B C Request R Request S Request T Request S Request T Request R Release R Release S Release T Release S Release T Release R
Here’s a possible deadlock scenario:
(^2) This related to the mutual exclusion used to avoid race conditions. Using locks or semaphores makes the code between the P and the V a mutually exclusive resource.