Dining philosophers problem
   HOME

TheInfoList



OR:

In
computer science Computer science is the study of computation, automation, and information. Computer science spans theoretical disciplines (such as algorithms, theory of computation, information theory, and automation) to practical disciplines (includi ...
, the dining philosophers problem is an example problem often used in
concurrent Concurrent means happening at the same time. Concurrency, concurrent, or concurrence may refer to: Law * Concurrence, in jurisprudence, the need to prove both ''actus reus'' and ''mens rea'' * Concurring opinion (also called a "concurrence"), a ...
algorithm design to illustrate synchronization issues and techniques for resolving them. It was originally formulated in 1965 by
Edsger Dijkstra Edsger Wybe Dijkstra ( ; ; 11 May 1930 – 6 August 2002) was a Dutch computer scientist, programmer, software engineer, systems scientist, and science essayist. He received the 1972 Turing Award for fundamental contributions to developing progra ...
as a student exam exercise, presented in terms of computers competing for access to
tape drive A tape drive is a data storage device that reads and writes data on a magnetic tape. Magnetic tape data storage is typically used for offline, archival data storage. Tape media generally has a favorable unit cost and a long archival stability. ...
peripherals. Soon after,
Tony Hoare Sir Charles Antony Richard Hoare (Tony Hoare or C. A. R. Hoare) (born 11 January 1934) is a British computer scientist who has made foundational contributions to programming languages, algorithms, operating systems, formal verification, and ...
gave the problem its present form.


Problem statement

Five philosophers dine together at the same table. Each philosopher has their own place at the table. There is a fork between each plate. The dish served is a kind of
spaghetti Spaghetti () is a long, thin, solid, cylindrical pasta.spaghetti
Dictionary.com. Dictionary.com Unabridg ...
which has to be eaten with two forks. Each philosopher can only alternately think and eat. Moreover, a philosopher can only eat their spaghetti when they have both a left and right fork. Thus two forks will only be available when their two nearest neighbors are thinking, not eating. After an individual philosopher finishes eating, they will put down both forks. The problem is how to design a regimen (a
concurrent Concurrent means happening at the same time. Concurrency, concurrent, or concurrence may refer to: Law * Concurrence, in jurisprudence, the need to prove both ''actus reus'' and ''mens rea'' * Concurring opinion (also called a "concurrence"), a ...
algorithm) such that no philosopher will starve; ''i.e.'', each can forever continue to alternate between eating and thinking, assuming that no philosopher can know when others may want to eat or think (an issue of incomplete information).


Problems

The problem was designed to illustrate the challenges of avoiding
deadlock In concurrent computing, deadlock is any situation in which no member of some group of entities can proceed because each waits for another member, including itself, to take action, such as sending a message or, more commonly, releasing a loc ...
, a system state in which no progress is possible. To see that a proper solution to this problem is not obvious, consider a proposal in which each philosopher is instructed to behave as follows: * think until the left fork is available; when it is, pick it up; * think until the right fork is available; when it is, pick it up; * when both forks are held, eat for a fixed amount of time; * put the left fork down; * put the right fork down; * repeat from the beginning. However, they each will think for an undetermined amount of time and may end up holding a left fork thinking, staring at the right side of the plate, unable to eat because there is no right fork, until they starve.
Resource starvation In computer science, resource starvation is a problem encountered in concurrent computing where a process is perpetually denied necessary resources to process its work. Starvation may be caused by errors in a scheduling or mutual exclusion algor ...
,
mutual exclusion In computer science, mutual exclusion is a property of concurrency control, which is instituted for the purpose of preventing race conditions. It is the requirement that one thread of execution never enters a critical section while a concurrent ...
and
livelock In concurrent computing, deadlock is any situation in which no member of some group of entities can proceed because each waits for another member, including itself, to take action, such as sending a message or, more commonly, releasing a loc ...
are other types of sequence and access problem.


Solutions


Dijkstra's solution

Dijkstra's solution uses one
mutex In computer science, a lock or mutex (from mutual exclusion) is a synchronization primitive: a mechanism that enforces limits on access to a resource when there are many threads of execution. A lock is designed to enforce a mutual exclusion concur ...
, one semaphore per philosopher and one
state variable A state variable is one of the set of variables that are used to describe the mathematical "state" of a dynamical system. Intuitively, the state of a system describes enough about the system to determine its future behaviour in the absence of a ...
per philosopher. This solution is more complex than the resource hierarchy solution. This is a C++20 version of Dijkstra's solution with Tanenbaum's changes: #include #include #include #include #include #include constexpr const size_t N = 5; // number of philosophers enum class State ; size_t inline left(size_t i) size_t inline right(size_t i) State state // array to keep track of everyone'both_forks_available state std::mutex critical_region_mtx; // mutual exclusion for critical regions std::mutex output_mtx; // for synchronized cout // one semaphore per philosopher std::binary_semaphore both_forks_available ; size_t my_rand(size_t min, size_t max) void test(size_t i) void think(size_t i) void take_forks(size_t i) void eat(size_t i) void put_forks(size_t i) void philosopher(size_t i) int main() The function test() and its use in take_forks() and put_forks() make the Dijkstra solution deadlock-free.


Resource hierarchy solution

This solution assigns a
partial order In mathematics, especially order theory, a partially ordered set (also poset) formalizes and generalizes the intuitive concept of an ordering, sequencing, or arrangement of the elements of a set. A poset consists of a set together with a bina ...
to the resources (the forks, in this case), and establishes the convention that all resources will be requested in order, and that no two resources unrelated by order will ever be used by a single unit of work at the same time. Here, the resources (forks) will be numbered 1 through 5 and each unit of work (philosopher) will always pick up the lower-numbered fork first, and then the higher-numbered fork, from among the two forks they plan to use. The order in which each philosopher puts down the forks does not matter. In this case, if four of the five philosophers simultaneously pick up their lower-numbered fork, only the highest-numbered fork will remain on the table, so the fifth philosopher will not be able to pick up any fork. Moreover, only one philosopher will have access to that highest-numbered fork, so he will be able to eat using two forks. This can intuitively be thought of as having one "left-handed" philosopher at the table, who -- unlike all the other philosophers -- takes his fork from the left first. While the resource hierarchy solution avoids deadlocks, it is not always practical, especially when the list of required resources is not completely known in advance. For example, if a unit of work holds resources 3 and 5 and then determines it needs resource 2, it must release 5, then 3 before acquiring 2, and then it must re-acquire 3 and 5 in that order. Computer programs that access large numbers of database records would not run efficiently if they were required to release all higher-numbered records before accessing a new record, making the method impractical for that purpose. The resource hierarchy solution is not ''fair''. If philosopher 1 is slow to take a fork, and if philosopher 2 is quick to think and pick its forks back up, then philosopher 1 will never get to pick up both forks. A fair solution must guarantee that each philosopher will eventually eat, no matter how slowly that philosopher moves relative to the others. The following source code is a C++11 implementation of the resource hierarchy solution for three philosophers. The sleep_for() function simulates the time normally spend with business logic. For GCC: compile with g++ src.cpp -std=c++11 -lpthread #include #include #include #include #include #include using namespace std; int myrand(int min, int max) void philosopher(int ph, mutex& ma, mutex& mb, mutex& mo) int main()


Arbitrator solution

Another approach is to guarantee that a philosopher can only pick up both forks or none by introducing an arbitrator, e.g., a waiter. In order to pick up the forks, a philosopher must ask permission of the waiter. The waiter gives permission to only one philosopher at a time until the philosopher has picked up both of their forks. Putting down a fork is always allowed. The waiter can be implemented as a mutex. In addition to introducing a new central entity (the waiter), this approach can result in reduced parallelism: if a philosopher is eating and one of his neighbors is requesting the forks, all other philosophers must wait until this request has been fulfilled even if forks for them are still available.


Limiting the number of diners in the table

A solution presented by William Stallings is to allow a maximum of ''n-1'' philosophers to sit down at any time. The last philosopher would have to wait (for example, using a semaphore) for someone to finish dining before they "sit down" and request access to any fork. This guarantees at least one philosopher may always acquire both forks, allowing the system to make progress.


Chandy/Misra solution

In 1984, K. Mani Chandy and J. MisraChandy, K.M.; Misra, J. (1984). /www.cs.utexas.edu/users/misra/scannedPdf.dir/DrinkingPhil.pdf The Drinking Philosophers Problem ACM Transactions on Programming Languages and Systems. proposed a different solution to the dining philosophers problem to allow for arbitrary agents (numbered ''P''1, ..., ''P''''n'') to contend for an arbitrary number of resources, unlike Dijkstra's solution. It is also completely distributed and requires no central authority after initialization. However, it violates the requirement that "the philosophers do not speak to each other" (due to the request messages). #For every pair of philosophers contending for a resource, create a fork and give it to the philosopher with the lower ID (''n'' for agent ''P''''n''). Each fork can either be ''dirty'' or ''clean.'' Initially, all forks are dirty. #When a philosopher wants to use a set of resources (''i.e.'', eat), said philosopher must obtain the forks from their contending neighbors. For all such forks the philosopher does not have, they send a request message. #When a philosopher with a fork receives a request message, they keep the fork if it is clean, but give it up when it is dirty. If the philosopher sends the fork over, they clean the fork before doing so. #After a philosopher is done eating, all their forks become dirty. If another philosopher had previously requested one of the forks, the philosopher that has just finished eating cleans the fork and sends it. This solution also allows for a large degree of concurrency, and will solve an arbitrarily large problem. It also solves the starvation problem. The clean/dirty labels act as a way of giving preference to the most "starved" processes, and a disadvantage to processes that have just "eaten". One could compare their solution to one where philosophers are not allowed to eat twice in a row without letting others use the forks in between. Chandy and Misra's solution is more flexible than that, but has an element tending in that direction. In their analysis, they derive a system of preference levels from the distribution of the forks and their clean/dirty states. They show that this system may describe a
directed acyclic graph In mathematics, particularly graph theory, and computer science, a directed acyclic graph (DAG) is a directed graph with no directed cycles. That is, it consists of vertices and edges (also called ''arcs''), with each edge directed from one v ...
, and if so, the operations in their protocol cannot turn that graph into a cyclic one. This guarantees that deadlock cannot occur. However, if the system is initialized to a perfectly symmetric state, like all philosophers holding their left side forks, then the graph is cyclic at the outset, and their solution cannot prevent a deadlock. Initializing the system so that philosophers with lower IDs have dirty forks ensures the graph is initially acyclic.


See also

* Cigarette smokers problem * Producers-consumers problem * Readers-writers problem * Sleeping barber problem


References


Bibliography

* *Dijkstra, E. W. (1971, June). /www.cs.utexas.edu/users/EWD/ewd03xx/EWD310.PDF Hierarchical ordering of sequential processes Acta Informatica 1(2): 115–138. *Lehmann, D. J., Rabin M. O, (1981). On the Advantages of Free Choice: A Symmetric and Fully Distributed Solution to the Dining Philosophers Problem. Principles Of Programming Languages 1981 (
POPL The annual ACM SIGPLAN- SIGACT Symposium on Principles of Programming Languages (POPL) is an academic conference in the field of computer science, with focus on fundamental principles in the design, definition, analysis, and implementation of prog ...
'81), pp. 133–138.


External links


Dining Philosophers Problem IDining Philosophers Problem IIDining Philosophers Problem III
* * * ttps://github.com/tlaplus/Examples/blob/master/specifications/DiningPhilosophers/DiningPhilosophers.tla Formal specification of the Chandy-Misra solution written in TLA+br>Distributed symmetric solutions
* /www.doc.ic.ac.uk/~jnm/concurrency/classes/Diners/Diners.html Interactive exampleof the Philosophers problem
Java
required)

* /www.cs.kent.ac.uk/projects/ofa/java-threads/0.html Wot No Chickens?Peter H. Welch proposed the Starving Philosophers variant that demonstrates an unfortunate consequence of the behaviour of Java thread monitors is to make thread starvation more likely than strictly necessary. * /www.cs.mtu.edu/~shene/NSF-3/e-Book/MUTEX/TM-example-philos-1.html ThreadMentorbr>Solving The Dining Philosophers Problem With Asynchronous Agents
{{DEFAULTSORT:Dining Philosophers Problem 1965 introductions Concurrency (computer science) Computational problems Edsger W. Dijkstra Problems in computer science Thought experiments Dutch inventions