The Philosopher's Dining Problem

The Synchronization Problem of Philosophers' Dining: Five philosophers sit around a round table, each with a plate of macaroni in front of them. Since the macaroni is so slippery, it takes two forks to grip. A fork is placed between two adjacent plates, and the dining table is shown in Figure 2-44.

 

There are two alternating periods of activity in the life of a philosopher: eating and thinking (this is just an abstraction that nothing else matters to the philosopher). When a philosopher feels hungry, he tries to take his left and right forks twice, one at a time, but in no particular order. If you manage to get two forks, start eating, put down your forks after eating and continue thinking. The key question is: Can you write a program for each philosopher that describes its behavior and never deadlocks? (The requirement to have two forks is an artificial rule, and we can also swap spaghetti for Chinese, rice instead of macaroni, and chopsticks instead of forks.)

Figure 2-45 shows an intuitive solution. The process take_fork will wait until the specified fork is available before taking it. However, this obvious solution is wrong . If five philosophers pick up the left fork at the same time , no one can get their right fork , and a deadlock occurs .

We can modify this program so that after getting the left fork, the program checks to see if the right fork is available. If it is not available, the philosopher puts down the left fork, waits for a while, and repeats the whole process . But this solution is also wrong , albeit for a different reason than the previous one. Maybe at some point all philosophers start the algorithm at the same time, pick up their left fork, see that the right fork is unavailable, put down the left fork, wait a while, pick up the left fork at the same time, and so on forever . In this case, all programs are running non-stop, but can not make progress , it is called starvation (starvation). (It's called starvation even if the problem doesn't happen at an Italian restaurant or a Chinese restaurant.)

   

Figure 2-45 A wrong solution to the dining philosophers problem

Now the reader might be thinking, "If the philosopher waits for a random amount of time when he can't get the right fork, instead of waiting for the same amount of time, then there is less chance of an interlock and things can go on." The idea is correct, and in almost all applications, try again later does not evolve into a problem. For example, in the popular local area network Ethernet, if two computers send packets at the same time, each computer waits a random amount of time before trying. In practice, the scheme works well. However, in a small number of applications, one would like to have a scheme that always works and cannot fail due to a string of unreliable random numbers (imagine a safety control system in a nuclear power plant).

The algorithm in Figure 2-45 can be improved as follows, which neither deadlocks nor starves : use a binary semaphore to protect the five statements after the call to think. Before starting to take the fork, the philosopher performs a down operation on the mutex. After putting the fork back, he performs an up operation on the mutex . In theory, this solution is feasible. But from a practical point of view, there are performance limitations: only one philosopher can eat at any one time. And five forks can actually allow two philosophers to eat at the same time.

The solution in Figure 2-46 is not only deadlock-free, but also achieves maximum parallelism for the case of any philosopher. The algorithm uses an array state to keep track of whether each philosopher is eating, thinking, or hungry (trying to get a fork). A philosopher is only allowed to enter the eating state when neither neighbor is eating . The neighbors of the i-th philosopher are defined by the macros LEFT and RIGHT, in other words, if i is 2, then LEFT is 1 and RIGHT is 3.

    
     

Figure 2-46 A solution to the dining philosophers problem

The program uses an array of semaphores, one for each philosopher, so that philosophers who want to eat are blocked when the desired fork is occupied. Note that each process runs the process philosopher as the main code, while the other processes take_forks, put_forks and test are just normal processes, not separate processes.



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325167617&siteId=291194637
Recommended