Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Dining philosophers problem
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
=== Resource hierarchy solution === This solution negates circular waiting by assigning a [[Partially ordered set|partial order]] 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 he plans 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 forks, 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.<ref name="formalization" /> 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 five philosophers. The sleep_for() function simulates the time normally spent with business logic.<ref>{{citation|title=Operating Systems - Design and Implementation, 3rd edition [Chapter: 3.3.5 Deadlock Prevention]|publisher=Pearson Education, Inc.|date=2006|first1=Andrew S.|last1=Tanenbaum}}</ref> For GCC: compile with <syntaxhighlight lang="bash">g++ src.cpp -std=c++11 -pthread</syntaxhighlight> <syntaxhighlight lang="c++"> #include <iostream> #include <chrono> #include <mutex> #include <thread> #include <random> #include <ctime> using namespace std; int myrand(int min, int max) { static mt19937 rnd(time(nullptr)); return uniform_int_distribution<>(min,max)(rnd); } void philosopher(int ph, mutex& ma, mutex& mb, mutex& mo) { for (;;) { // prevent thread from termination int duration = myrand(200, 800); { // Block { } limits scope of lock lock_guard<mutex> gmo(mo); cout<<ph<<" thinks "<<duration<<"ms\n"; } this_thread::sleep_for(chrono::milliseconds(duration)); { lock_guard<mutex> gmo(mo); cout<<"\t\t"<<ph<<" is hungry\n"; } lock_guard<mutex> gma(ma); // sleep_for() Delay before seeking second fork can be added here but should not be required. lock_guard<mutex> gmb(mb); duration = myrand(200, 800); { lock_guard<mutex> gmo(mo); cout<<"\t\t\t\t"<<ph<<" eats "<<duration<<"ms\n"; } this_thread::sleep_for(chrono::milliseconds(duration)); } } int main() { cout<<"dining Philosophers C++11 with Resource hierarchy\n"; mutex m1, m2, m3, m4, m5; // 5 forks are 5 mutexes mutex mo; // for proper output // 5 philosophers are 5 threads thread t1([&] {philosopher(1, m1, m2, mo);}); thread t2([&] {philosopher(2, m2, m3, mo);}); thread t3([&] {philosopher(3, m3, m4, mo);}); thread t4([&] {philosopher(4, m4, m5, mo);}); thread t5([&] {philosopher(5, m1, m5, mo);}); // Force a resource hierarchy t1.join(); // prevent threads from termination t2.join(); t3.join(); t4.join(); t5.join(); } </syntaxhighlight>
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)