-
Home
- Model checking concurrent
- Model checking concurrent
- Modeling concurrent processes:
The Dining Philosophers Problem is a standard example of concurrent
programming. The idea is that a group of
philosophers sit at a single round table for dinner.
There are
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.
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.