<< Chapter < Page Chapter >> Page >

The Dining Philosophers Problem is a standard example of concurrent programming. The idea is that a group of n philosophers sit at a single round table for dinner. There are n forks, one placed between each plate. To successfully eat each bite, a philosopher needs both of theadjacent forks. Thus, as one consequence, two adjacent philosophers cannot eat at the same time, since they cannot both have the forkinbetween them at the same time. The question is what strategies can the philosophers have such that, each philosopher eventuallyeats. Typically, but not necessarily, we also require that each philosopher has the same strategy.

To keep the problem small, let's assume we have three philosophers.As a slight simplication of some of the following problems, we'll ignore maxims about code reuse, and choose to useseparate procedures for each philsopher's strategy.

  • Here is one attempted solution. Repeatedly, each philosopher tries to pick up the left fork,then tries to pick up the right fork, and then eats and drops the forks.A problem with this solution is that it has a race condition -- two philosophers can have the same fork at the same time.
    • Run this code in SPIN. Provide some output from a sample run.
    • Add appropriate assert statements to the code to test for a race condition. If necessary, you may add other codeto keep track of information to use in these assertions.
    • Use SPIN to find a shortest trace illustrating a race condition.
  • Here is another attempted solution. It uses the same strategy, except that each fork has a lock.A problem with this solution is that it can deadlock.
    • Use SPIN to show that the previous race conditions cannot happen.
    • Use SPIN to find a shortest trace illustrating deadlock.
    • Recode this version so it uses multiple copies of only a single proctype .
  • Informally, deadlock is often viewed in the more restrictive sense of deadlocking on the acquisition of locks.This is equivalent to considering the case where the only guard conditions are those testing boolean locks.In this sense, deadlock can only happen where there are at least two locks involved. The following problems are instances oftwo general strategies for avoiding this: using fewer locks or being careful with locks.In the following, code reuse will not matter -- you may write code using either a single or multiple proctype s.One attempt is to only have a lock for only every other fork.The idea is that each philosopher only needs to grab one lock.
    • Modify the code to do this with an even number of philosophers and forks, say four of each.
    • Does this code have the race condition or deadlock? Use SPIN to determine this.If no, show SPIN's successful output. If yes, find a shortest trace illustrating the problem.
  • A well-known solution is to number the forks somehow and ensurethat locks are always obtained in numerical order (instead of always left-then-right).Note: Maintain the provided lock-based code's lock convention of first-acquired last-released.
    • Modify the code to do this.
    • Use SPIN to show that this does not have race conditions or deadlock.
    • Use SPIN to determine whether using a first-acquired first-released protocol has race conditionsor deadlock.
  • Assume that philosophers always try to pick up both forks,eat, and then drop both forks, all philsophers use the same strategy, but we have not chosen a particular strategy yet.If we assume weak fairness is enforced and deadlock is avoided, does each philosopher eat repeatedly? What if we assumestrong fairness?
  • You should add assertions to each philosopher,immediately before or after the printf . They assert that the two forks are being held by thatphilosopher.
  • The key to recoding is to use _pid , so that each process (philosopher) knows its number.Since process numbers start with 0, not 1, you can either use _pid+1 , or renumber the philosophers 02. Then, replace the type="inline">mtype with a simple numerical encoding.To compute the appropriate right_fork value, use the modulo operator ( % ).
  • If any fork lacks a lock, race conditions are possible.
  • Using a FIFO acquisition and release protocol does not changecorrectness. With left-then-right acquisition, the problem can still deadlock, while with a numerical acquisition,it doesn't. After all, the deadlock is a result of the acquisition strategy, not the release strategy.
  • Weak fairness is conditional on processes beingcontinuously enabled. But here, when one philosopher grabs a fork, theadjacent philosopher sharing that fork is no longer enabled. So with three philosophers, one philosopher eating repeatedlyis weakly fair. Similarly, with four philosophers, two of them sitting opposite who are eating repeatedly is weakly fair.Strong fairness is conditional on processes beingenabled infinitely often. It also does not imply that each philosophergets to eat. For example, consider four philosophers 14 and four forks AD. After starting with2 grabs A, 2 grabs B, they can cycle through the following actions:4 grabs C, 2 drops B, 4 grabs D, 2 drops A, 4 drops D, 2 grabs A, 4 drops C, 2 grabs B.The other two philosophers are never enabled, and thus it is strongly fair for them not to eat.

Get Jobilize Job Search Mobile App in your pocket Now!

Get it on Google Play Download on the App Store Now




Source:  OpenStax, Model checking concurrent programs. OpenStax CNX. Oct 27, 2005 Download for free at http://cnx.org/content/col10294/1.3
Google Play and the Google Play logo are trademarks of Google Inc.

Notification Switch

Would you like to follow the 'Model checking concurrent programs' conversation and receive update notifications?

Ask