Dining philosophers: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(16 intermediate revisions by 11 users not shown)
Line 13:
{{libheader|Simple components for Ada}}
The following solution uses an array of [[mutex]]es in order to model the forks. The forks used by a philosopher compose a subset in the array. When the the philosopher seizes his forks from the subset the array object prevents deadlocking since it is an atomic operation.
<langsyntaxhighlight lang="ada">with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;
with Ada.Text_IO; use Ada.Text_IO;
 
Line 62:
begin
null; -- Nothing to do in the main task, just sit and behold
end Test_Dining_Philosophers;</langsyntaxhighlight>
===Ordered mutexes===
In the following solution forks are implemented as plain [[mutex]]es. The deadlock is prevented by ordering mutexes. Philosopher tasks seize them in same order 1, 2, 3, 4, 5.
<langsyntaxhighlight lang="ada">with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;
with Ada.Text_IO; use Ada.Text_IO;
 
Line 117:
begin
null; -- Nothing to do in the main task, just sit and behold
end Test_Dining_Philosophers;</langsyntaxhighlight>
===Host of the dining room===
Both deadlocks happen when all philosophers are in the dining room. The following solution has a host of the room who chatters the last philosopher while four of them are in the room. So there are never more than four of them in there, which prevents deadlock. Now the forks can be picked up in a "wrong" order, i.e. the left one first.
<langsyntaxhighlight lang="ada">with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;
with Ada.Text_IO; use Ada.Text_IO;
 
Line 194:
begin
null; -- Nothing to do in the main task, just sit and behold
end Test_Dining_Philosophers;</langsyntaxhighlight>
 
=={{header|AutoHotkey}}==
Line 202:
Starvation will only occur if one (or more) of the philosophers never stops eating.
Try changing EnoughForks to 4 and fork supply per philosopher to 2.
<langsyntaxhighlight lang="ahk">#Persistent
SetWorkingDir, %A_ScriptDir%
FileDelete, output.txt
Line 343:
CurrentWaitCount++
}
}</langsyntaxhighlight>
{{out}}
<pre style="height:40ex;overflow:scroll">Aristotle is hungry.
Line 447:
⋮</pre>
 
=={{header|BBC BASIC}}==
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
This avoids deadlocks using the same strategy as the C solution (one of the philosophers picks up the left fork first).
<langsyntaxhighlight lang="bbcbasic"> INSTALL @lib$+"TIMERLIB"
nSeats% = 5
Line 515 ⟶ 516:
PROC_killtimer(tID%(I%))
NEXT
ENDPROC</langsyntaxhighlight>
'''Sample output:'''
<pre>
Line 552 ⟶ 553:
=={{header|C}}==
Avoid deadlocks by making each philosopher have a different order of picking up forks. As long as one person waits for left fork first and another waits for right first, cycles can't form.
<langsyntaxhighlight lang="c">#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
Line 646 ⟶ 647:
/* wait forever: the threads don't actually stop */
return pthread_join(tid[0], 0);
}</langsyntaxhighlight>
 
This uses a modified version of the Python algorithm version below. Uses POSIX threads.
<langsyntaxhighlight Clang="c">#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
Line 742 ⟶ 743:
Ponder();
return 0;
}</langsyntaxhighlight>
 
This version uses C11 threads and the approach of making one of the philosophers left-handed to avoid deadlock.
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <threads.h>
#include <stdlib.h>
Line 805 ⟶ 806:
return 0;
}
</syntaxhighlight>
</lang>
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight Clang="c sharp">
using System;
using System.Collections.Generic;
Line 1,057 ⟶ 1,058:
class Fork { }
}
</syntaxhighlight>
</lang>
 
=={{header|C++}}==
Uses C++17
<langsyntaxhighlight lang="cpp">#include <algorithm>
#include <array>
#include <chrono>
Line 1,186 ⟶ 1,187:
}};
Message("It is dark outside...");
}</langsyntaxhighlight>
<div style="height:10em; overflow:auto; border: 1px solid #AAA">
Dinner started!<br>
Line 1,274 ⟶ 1,275:
. . . .<br>
</div>
Uses C++14
Without threads, uses state machine.
<syntaxhighlight lang="cpp">
#include <iostream>
#include <vector>
#include <random>
#include <memory>
#include <cassert>
 
using namespace std;
 
struct Fork {
static const int ON_TABLE = -1;
int holder = ON_TABLE;
int request = ON_TABLE;
int id;
bool dirty = true;
Fork(int id) {
this->id = id;
}
bool isRequest() {
return request != Fork::ON_TABLE;
}
 
void process(int &forkCount, int &dirtyCount) {
if (holder == id) {
forkCount++;
if (isRequest()) {
if (dirty) {
forkCount--;
dirty = false;
holder = request;
}
request = Fork::ON_TABLE;
}
}
else
if (holder == Fork::ON_TABLE) {
holder = id;
forkCount++;
assert(dirty);
dirtyCount++;
assert(request == Fork::ON_TABLE);
} else {
request = id;
}
}
};
 
class Table;
 
enum State { Have0Forks, Have1Fork,Have01Fork, Have2Forks, Eat, AfterEat, Pon };
 
class Philosopher {
int id;
Table *table;
public:
Fork* left;
Fork* right;
int eatStarts = 0;
Philosopher(Table *table, int id);
void naive();
void ChandyMisra();
State state;
 
void selectState(int forkCount, int dirtyCount);
};
 
class Table {
mt19937 mt_rand;
std::uniform_real_distribution<> dis;
unique_ptr<std::uniform_int_distribution<>> disint;
public:
static const int PhilCount = 5;
vector<unique_ptr<Philosopher>> philosophers;
vector<unique_ptr<Fork>> forks;
Table() {
mt_rand.seed(1234);
disint = make_unique<std::uniform_int_distribution<>>(0, PhilCount-1);
for (int i=0; i<PhilCount; i++)
forks.push_back(make_unique<Fork>(i));
for (int i=0; i<PhilCount; i++)
philosophers.push_back(make_unique<Philosopher>(this, i));
}
double rand() {
return dis(mt_rand);
}
 
double randInt() {
return (*disint)(mt_rand);
}
void naive() {
cout << "Naive algorithm" << endl;
for (int i=0; i<Table::PhilCount; i++)
philosophers[i]->state = State::Have0Forks;
for (int i=0; i<100000; i++) {
philosophers[randInt()]->naive();
}
for (int i=0; i<Table::PhilCount; i++)
cout << i << " : " << philosophers[i]->eatStarts << endl;
}
void ChandyMisra() {
cout << "Chandy-Misra algorithm" << endl;
for (int i=0; i<Table::PhilCount; i++) {
philosophers[i]->state = State::Have01Fork;
philosophers[i]->eatStarts = 0;
philosophers[i]->left->holder = i;
}
for (int i=0; i<100000; i++) {
philosophers[randInt()]->ChandyMisra();
}
for (int i=0; i<Table::PhilCount; i++)
cout << i << " : " << philosophers[i]->eatStarts << endl;
}
};
 
Philosopher::Philosopher(Table *table, int id):table(table), id(id) {
left = table->forks[id].get();
right = table->forks[(id+1) % Table::PhilCount].get();
}
 
void Philosopher::naive() {
switch (state) {
case State::Pon:
if (table->rand()<0.2)
state = State::Have0Forks;
return;
case State::Have0Forks:
int forkCount;
forkCount = 0;
if (left->holder==Fork::ON_TABLE) {
left->holder=id;
forkCount++;
}
if (right->holder==Fork::ON_TABLE) {
right->holder=id;
forkCount++;
}
if (forkCount==1)
state = State::Have1Fork;
else if (forkCount==2)
state = State::Have2Forks;
return;
case State::Have1Fork:
Fork* forkToWait;
if (left->holder==id)
forkToWait = right;
else
forkToWait = left;
if (forkToWait->holder==Fork::ON_TABLE) {
forkToWait->holder=id;
state = State::Have2Forks;
}
return;
case State::Have2Forks:
state = State::Eat;
eatStarts++;
return;
case State::Eat:
if (table->rand()<0.2)
state = State::AfterEat;
return;
case State::AfterEat:
left->holder = Fork::ON_TABLE;
right->holder = Fork::ON_TABLE;
state = State::Pon;
return;
}
}
 
void Philosopher::ChandyMisra() {
switch (state) {
case State::Pon:
if (table->rand() < 0.2)
state = State::Have01Fork;
return;
case State::Have01Fork:
int forkCount;
int dirtyCount;
forkCount = 0;
dirtyCount = 0;
left->process(forkCount, dirtyCount);
right->process(forkCount, dirtyCount);
selectState(forkCount, dirtyCount);
return;
case State::Have2Forks:
state = State::Eat;
eatStarts++;
return;
case State::Eat:
if (table->rand()<0.2)
state = State::AfterEat;
return;
case State::AfterEat:
if (left->request!=Fork::ON_TABLE) {
left->dirty = false;
left->holder = left->request;
left->request = Fork::ON_TABLE;
} else {
left->holder = Fork::ON_TABLE;
left->dirty = true;
}
 
if (right->request!=Fork::ON_TABLE) {
right->dirty = false;
right->holder = right->request;
right->request = Fork::ON_TABLE;
} else {
right->holder = Fork::ON_TABLE;
right->dirty = true;
}
state = State::Pon;
return;
}
}
 
void Philosopher::selectState(int forkCount, int dirtyCount) {
if (forkCount == 2 && dirtyCount==0)
state = State::Have2Forks;
else
state = State::Have01Fork;
}
 
int main() {
Table table;
table.naive();
table.ChandyMisra();
return 0;
}
</syntaxhighlight>
 
=={{header|Clojure}}==
Clojure's STM allows us to avoid low-level synchronization primitives like semaphores. In order to simulate the Dining Philosophers scenario, the forks are [http://clojure.org/refs references] to a boolean indicating whether or not it is available for use. Each philosopher (also held in a ref) has a fixed amount of food he will try to eat, first by trying to acquire both forks, eating for some period of time, releasing both forks, then thinking for some period of time; if the forks cannot be acquired, the philosopher waits for a fixed amount of time and tries again.
<langsyntaxhighlight lang="clojure">(defn make-fork []
(ref true))
 
Line 1,306 ⟶ 1,537:
(stop-eating phil)
(Thread/sleep (rand-int max-think-duration)))
(Thread/sleep retry-interval))))</langsyntaxhighlight>
The second line of the <tt>start-eating</tt> function contains the essential solution: by invoking <tt>ensure</tt> on every fork reference, we are guaranteed that the state of the forks will not be modified by other transactions, thus we can rely on those values for the rest of the transaction. Now we just need to run it:
<langsyntaxhighlight lang="clojure">(def *forks* (cycle (take 5 (repeatedly #(make-fork)))))
 
(def *philosophers*
Line 1,327 ⟶ 1,558:
(println (str (:name p)
": eating=" (:eating? p)
" food=" (:food p)))))))</langsyntaxhighlight>
The <tt>status</tt> function inspects the data structures within a transaction so as to give consistent results (e.g., every unavailable fork has exactly one "eating" philosopher adjacent).
 
Line 1,338 ⟶ 1,569:
Random times are calculated based upon a normal distribution; the main loop doesn't sleep to wait for all philosophers to end dining, it uses a condition variable instead.
 
<langsyntaxhighlight lang="lisp">(in-package :common-lisp-user)
 
;;
Line 1,418 ⟶ 1,649:
(bt:with-lock-held (lock)
(bt:condition-wait condition lock)))))
</syntaxhighlight>
</lang>
Alternative solution using library STMX which provides Software Transactional Memory, as well as BORDEAUX-THREADS above. Depends on Quicklisp. TAKE will wait until something is available in a TCELL, then remove it. PUT will wait for a TCELL to become empty, then add it. ATOMIC ensures STM operations in its body happen atomically.
<langsyntaxhighlight lang="lisp">(ql:quickload '(:stmx :bordeaux-threads))
 
(defpackage :dining-philosophers
Line 1,469 ⟶ 1,700:
:initial-bindings (cons (cons '*standard-output* *standard-output*)
bt:*default-special-bindings*))))))
</syntaxhighlight>
</lang>
{{out}}
<langsyntaxhighlight lang="lisp">DINING-PHILOSOPHERS> (scenario)
Aristotle is hungry
Aristotle is eating
Line 1,514 ⟶ 1,745:
Spinoza is thinking
Marx is eating
...</langsyntaxhighlight>
 
=={{header|D}}==
This code is using a strict order for the forks/mutexes to prevent a deadlock.
 
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.string, std.parallelism,
core.sync.mutex;
 
Line 1,557 ⟶ 1,788:
}
}
}</langsyntaxhighlight>
{{out|Sample output}}
<pre>Spinoza is full.
Line 1,578 ⟶ 1,809:
{{Trans|Pascal}}
Just a fix of Pascal version to run in Delphi
<syntaxhighlight lang="delphi">
<lang Delphi>
program dining_philosophers;
uses
Line 1,680 ⟶ 1,911:
WaitForDinnerOver;
readln;
end.</langsyntaxhighlight>
 
=={{header|E}}==
Line 1,689 ⟶ 1,920:
We introduce a laquais who checks that no more than 4 philosophers are sitting at the same time. This prevents deadlocks. Reference : [http://greenteapress.com/semaphores/downey08semaphores.pdf The little book of semaphores].
 
<langsyntaxhighlight lang="scheme">
(lib 'tasks)
 
Line 1,729 ⟶ 1,960:
i)
(define tasks (for/vector ((i 5)) (make-task philo i)))
</syntaxhighlight>
</lang>
{{out}}
<langsyntaxhighlight lang="scheme">
(define (observe dummmy)
(writeln 'observer 'rounds= rounds)
Line 1,742 ⟶ 1,973:
 
(dinner)
</syntaxhighlight>
</lang>
<small>
Marx thinking about philosophy. <br>
Line 1,805 ⟶ 2,036:
The example uses numbers (versus names) to identify the philosophers in order to allow the user to vary the number of philosophers.
 
<langsyntaxhighlight lang="eiffel ">class
DINING_PHILOSOPHERS
 
Line 1,862 ⟶ 2,093:
end
 
end -- class DINING_PHILOSOPHERS</langsyntaxhighlight>
<langsyntaxhighlight lang="eiffel ">class
PHILOSOPHER
 
Line 1,972 ⟶ 2,203:
valid_has_eaten_count: has_eaten_count <= round_count
 
end -- class PHILOSOPHER</langsyntaxhighlight>
<langsyntaxhighlight lang="eiffel ">class
FORK
 
Line 2,006 ⟶ 2,237:
end
 
end -- class FORK</langsyntaxhighlight>
 
=={{header|Elixir}}==
Implements the Chandy-Misra algorithm.
 
<syntaxhighlight lang="elixir">
<lang Elixir>
defmodule Philosopher do
Line 2,133 ⟶ 2,364:
change_state(pid)
end
</syntaxhighlight>
</lang>
 
=={{header|Erlang}}==
===Waiter-based===
<langsyntaxhighlight lang="erlang">
%%%
%%% to compile and run:
Line 2,262 ⟶ 2,493:
unregister(diningRoom).
 
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,387 ⟶ 2,618:
</pre>
===Free-thinkers===
<langsyntaxhighlight lang="erlang">
%%% This version uses free-running 'phil' agents (actors) and
%%% state machines representing the forks.
Line 2,586 ⟶ 2,817:
.
 
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,709 ⟶ 2,940:
 
=={{header|Euphoria}}==
<langsyntaxhighlight Euphorialang="euphoria">constant FREE = 0, LOCKED = 1
sequence forks
forks = repeat(FREE,5)
Line 2,762 ⟶ 2,993:
while get_key() = -1 do
task_yield()
end while</langsyntaxhighlight>
 
Sample output:
Line 2,814 ⟶ 3,045:
This solution avoids deadlock by employing a waiter.
 
<langsyntaxhighlight lang="fsharp">
open System
 
Line 2,867 ⟶ 3,098:
Console.ReadLine() |> ignore
0
</syntaxhighlight>
</lang>
 
=={{header|Go}}==
===Channels===
Goroutine synchronization done with Go channels. Deadlock prevented by making one philosopher "left handed."
<langsyntaxhighlight lang="go">package main
 
import (
Line 2,955 ⟶ 3,186:
}
fmt.Println("table empty")
}</langsyntaxhighlight>
Output:
<pre>
Line 3,026 ⟶ 3,257:
 
One more concurrency technique actually used in both solutions is to use the log package for output rather than the fmt package. Output from concurrent goroutines can get accidentally interleaved in some cases. While neither package makes claims about this problem, the log package historically has been coded to avoid interleaved output.
<langsyntaxhighlight lang="go">package main
 
import (
Line 3,084 ⟶ 3,315:
dining.Wait() // wait for philosphers to finish
fmt.Println("table empty")
}</langsyntaxhighlight>
 
=={{header|Groovy}}==
Deadlocks are avoided by always getting locks on forks with lower numbers first.
<langsyntaxhighlight lang="groovy">import groovy.transform.Canonical
 
import java.util.concurrent.locks.Lock
Line 3,143 ⟶ 3,374:
}
 
diningPhilosophers(['Aristotle', 'Kant', 'Spinoza', 'Marx', 'Russell'])</langsyntaxhighlight>
 
=={{header|Haskell}}==
Using the built-in Software Transactional Memory in GHC.
<langsyntaxhighlight lang="haskell">module Philosophers where
 
import Control.Monad
Line 3,212 ⟶ 3,443:
-- All threads exit when the main thread exits.
getLine
</syntaxhighlight>
</lang>
 
==Icon and {{header|Unicon}}==
Line 3,223 ⟶ 3,454:
when they can't get both forks and went back to thinking instead. (Take away their grant money.)
 
<langsyntaxhighlight lang="unicon">global forks, names
 
procedure main(A)
Line 3,251 ⟶ 3,482:
}
}
end</langsyntaxhighlight>
 
A sample run, terminated after some time.
Line 3,306 ⟶ 3,537:
 
=={{header|J}}==
===Using Threading Primitives===
 
Currently, this only works under jconsole. (Unfortunately, QT requires all GUI interactions occur on the main thread, and as of j9.4, jqt has not been updated force this behavior, so do not use jqt here.)
 
Here, to prevent deadlock, philosophers always pick up forks in a specific order and always lay down their forks in the reverse order. This means that one philosopher (Marx) will use the opposite left/right order from the rest of the philosophers.
 
<syntaxhighlight lang=J>reqthreads=: {{ 0&T.@''^:(0>.y-1 T.'')0 }}
dispatchwith=: (t.'')every
newmutex=: (; 10&T.@0)@>
lock=: 11&T.@{:
unlock=: 13&T.@{:
dl=: 6!:3
 
dine=: {{
'forkA forkB'=. <"1 /:~ n
announce=. m {{ echo m,' ',y }}
announce 'will use fork ',(":;{.forkA),' first and put it down last'
announce 'will use fork ',(":;{.forkB),' second and put it down first'
dl 1
while. do.
announce 'is hungry'
lock forkA
announce 'picked up fork ',":;{.forkA
lock forkB
announce 'picked up fork ',":;{.forkB
announce 'is eating'
dl 2+(?3e3)%1e3
announce 'has finished eating'
unlock forkB
announce 'has put down fork ',":;{.forkB
unlock forkA
announce 'has put down fork ',":;{.forkA
announce 'has left the room'
dl 4+(?1e4)%1e3
end.
y
}}
 
start=: {{
echo 'Hit enter to exit'
dl 1
reqthreads 5
forks=. newmutex i.5
for_philosopher.;:' Aristotle Kant Spinoza Marx Russell' do.
forks=. 1|.forks
(;philosopher) dine (2{.forks) dispatchwith EMPTY
end.
exit 1!:1]1
}}
</syntaxhighlight>
 
Sample session:
 
<syntaxhighlight lang=J>
start''
Hit enter to exit
Aristotle will use fork 1 first and put it down last
Kant will use fork 2 first and put it down last
Marx will use fork 0 first and put it down last
Spinoza will use fork 3 first and put it down last
Russell will use fork 0 first and put it down last
Aristotle will use fork 2 second and put it down first
Kant will use fork 3 second and put it down first
Marx will use fork 4 second and put it down first
Spinoza will use fork 4 second and put it down first
Russell will use fork 1 second and put it down first
Spinoza is hungry
Marx is hungry
Aristotle is hungry
Aristotle picked up fork 1
Spinoza picked up fork 3
Marx picked up fork 0
Kant is hungry
Aristotle picked up fork 2
Spinoza picked up fork 4
Aristotle is eating
Spinoza is eating
Russell is hungry
Aristotle has finished eating
Spinoza has finished eating
Aristotle has put down fork 2
Kant picked up fork 2
Spinoza has put down fork 4
Marx picked up fork 4
Aristotle has put down fork 1
Spinoza has put down fork 3
Kant picked up fork 3
Marx is eating
Aristotle has left the room
Spinoza has left the room
Kant is eating
Kant has finished eating
Marx has finished eating
Kant has put down fork 3
Marx has put down fork 4
Kant has put down fork 2
Marx has put down fork 0
Russell picked up fork 0
Kant has left the room
Marx has left the room
Russell picked up fork 1
Russell is eating</syntaxhighlight>
 
===Older Emulations===
These philosophers are very smart and polite: they figured out immediately that at most two of them can eat simultaneously (take the floor of n divided by 2 for n philosophers); so, when they are hungry and it is necessary, they wait in line. (In general, for n > 1, because they are very smart and polite, when a philosopher seats he leaves exactly one empty seat between himself and one of the philosophers which are already eating if any.)
 
J does not support concurrency; so, this is a discrete-event simulation (DES). The time spent thinking and eating is assumed to be exponentially distributed, respectively, at the rates of 1 and 0.5 per time unit.
 
====The simulation code====
The simulation is defined in terms of fixed tacit (stateless point-free) code (a Turing complete dialect of J; see, https://rosettacode.org/wiki/Universal_Turing_machine#J),
 
<langsyntaxhighlight lang="j">". noun define -. CRLF NB. Fixed tacit simulation code...
 
simulate=.
Line 3,339 ⟶ 3,674:
) ,&< ''"_) 0 6} ]))@:(,&(;:8$','))@:;
 
)</langsyntaxhighlight>
 
====Simulation of 11 chronological events for five philosophers====
<langsyntaxhighlight lang="j"> 'Aristotle Kant Spinoza Marx Russell' simulate 11
0.000: All of them start thinking.
0.097: Spinoza starts eating.
Line 3,359 ⟶ 3,694:
5.166: Marx starts eating.
5.915: Marx starts thinking.
5.915: Spinoza starts eating.</langsyntaxhighlight>
 
====Simulation of 22 chronological events for eight philosophers====
<langsyntaxhighlight lang="j"> 'Aristotle Kant Spinoza Marx Russell Laozi Nezahualcoyotl Averroes' simulate 22
0.000: All of them start thinking.
0.077: Nezahualcoyotl starts eating.
Line 3,392 ⟶ 3,727:
2.339: Marx starts waiting and thinking about hunger.
2.446: Aristotle starts thinking.
2.446: Marx starts eating.</langsyntaxhighlight>
 
====The structured derivation of the verb (function)====
 
The fixed tacit code of the verb (simulate) was produced by means of an unorthodox tacit toolkit; however, the verb produced is orthodox (compliant):
 
<langsyntaxhighlight lang="j">NB. Quick and dirty tacit toolkit...
o=. @:
Line 3,491 ⟶ 3,826:
A`(amend o ((B P A)f))h o (B`0: h) NB. Activity: thinking
[ echo o ( time , ' starts thinking.' ,~ P {:: N)
dequeue ^: (1 <: # o Q) NB. dequeuingDequeuing a philosopher (if possible)
)
 
Line 3,513 ⟶ 3,848:
 
NB. The simulation code is produced by the sentence,
NB. 77 (-@:[ ]\ 5!:5@<@:]) 'simulate'</langsyntaxhighlight>
 
=={{header|Java}}==
This Java implementation uses a token system. If a philosopher's number is on the token, they pick up their left and right forks. Passing the token to their immediate neighbor would be pointless, so they increment the token by 2, passing it to the philosopher after their neighbor. The +2 works well for odd numbers of philosophers. With wait down at 1 millisecond I get about 1.5M eats/sec running 5 philosophers, down to about 0.5M eats/sec running 25. The single token generates good availability for 80% of 5 forks, but a much lower availability % of 25 forks.
<syntaxhighlight lang="java">
<lang Java>
package diningphilosophers;
 
Line 3,631 ⟶ 3,966:
}
}
</syntaxhighlight>
</lang>
 
{{out}}
<pre>
|Eat|Get|Eat|Get|Get| |P00|P00|P02|P02|P04|
|Eat|Get|Get|Get|Get| |P00|P00| | | |
|Get|Get|Get|Get|Get| | | | | | |
|Get|Pon|Get|Pon|Get| |P00| | | | |
|Eat|Get|Get|Get|Get| |P00|P00| | | |
|Get|Eat|Get|Get|Pon| | |P01|P01| | |
|Pon|Get|Eat|Get|Eat| |P04| |P02|P02|P04|
|Get|Get|Get|Get|Pon| | | | |P03| |
|Pon|Get|Eat|Pon|Get| | | |P02|P02|P04|
|Get|Eat|Pon|Get|Eat| |P04|P01|P01| | |
|Get|Pon|Get|Get|Get| | | | |P03| |
|Eat|Get|Get|Pon|Get| |P00|P00| | | |
|Get|Pon|Get|Get|Get| |P00| | | | |
|Get|Get|Eat|Get|Eat| |P04|P01|P02|P02|P04|
|Pon|Pon|Eat|Get|Get| | | |P02|P02| |
P00: ate 59 times, 3/sec
P01: ate 59 times, 3/sec
P02: ate 59 times, 3/sec
P03: ate 59 times, 3/sec
P04: ate 59 times, 3/sec
</pre>
 
=={{header|JoCaml}}==
Line 3,648 ⟶ 4,007:
*The mean time of waiting while hungry is not bounded and grows very slowly (logarithmically) with time.
 
<langsyntaxhighlight lang="jocaml">let random_wait n = Unix.sleep (Random.int n);;
let print s m = Printf.printf "philosopher %s is %s\n" s m; flush(stdout);;
let will_eat s = print s "eating"; random_wait 10;;
Line 3,668 ⟶ 4,027:
and e() = will_think "Russell"; eh()
;;
spawn fab() & fbc() & fcd() & fde() & fea() & a() & b() & c() & d() & e();;</langsyntaxhighlight>
Sample output:
<pre>philosopher Aristotle is thinking
Line 3,704 ⟶ 4,063:
This solution is logically the same as the "minimal simple" solution above, but now the timing information is printed. Statistical information is also printed on hungry waiting time before eating: average among all instances of eating, and maximum time ever waited by anyone.
 
<langsyntaxhighlight lang="jocaml">let print s t m = Printf.printf "t=%d: philosopher %s is %s\n" t s m; flush(stdout);;
let random_wait n = Unix.sleep (Random.int n);;
 
Line 3,750 ⟶ 4,109:
 
(* now we need to wait and do nothing; nobody will be able to inject godot() *)
def wait_forever() & godot() = reply () to wait_forever in wait_forever();;</langsyntaxhighlight>
Sample output (excerpt):
<pre>t=2: philosopher Aristotle is thinking
Line 3,793 ⟶ 4,152:
This solution implements "fairness" -- if two neighbors are hungry, the one who waited more will eat first. The waiting time for each philosopher is bounded by twice the maximum eating time.
 
<langsyntaxhighlight lang="jocaml">#!/usr/bin/jocamlrun jocaml
 
(* eating and thinking between 0 and this-1 *)
Line 3,869 ⟶ 4,228:
(* now we need to wait and do nothing; nobody will be able to inject godot() *)
 
def wait_forever() & godot() = reply () to wait_forever in wait_forever();;</langsyntaxhighlight>
 
Sample output:
Line 3,899 ⟶ 4,258:
and the others take the right fork first. The forks are represented by 5 channels.
One lefty's taking left fork before right prevents deadlocks (see C solution).
<langsyntaxhighlight lang="julia">
mutable struct Philosopher
name::String
Line 3,983 ⟶ 4,342:
 
runall(tasks)
</syntaxhighlight>
</lang>
{{output}}
Aristotle is out of the dining room for now.
Line 4,060 ⟶ 4,419:
{{trans|Groovy}}
As noted in the Groovy entry, deadlocks are avoided by always getting locks on forks with lower numbers first.
<langsyntaxhighlight lang="scala">// Version 1.2.31
 
import java.util.Random
Line 4,117 ⟶ 4,476:
val names = listOf("Aristotle", "Kant", "Spinoza", "Marx", "Russell")
diningPhilosophers(names)
}</langsyntaxhighlight>
 
=={{header|Logtalk}}==
Works when using SWI-Prolog, XSB, or YAP as the backend compiler:
<langsyntaxhighlight lang="logtalk">:- category(chopstick).
 
% chopstick actions (picking up and putting down) are synchronized using a notification
Line 4,276 ⟶ 4,635:
right_chopstick(cs5). % in different order from the other philosophers
 
:- end_object.</langsyntaxhighlight>
 
=={{header|M2000 Interpreter}}==
Line 4,294 ⟶ 4,653:
The critical variable get new value from another thread the Main.Task. Some times critical may get a value of 7 and then the thinking philosopher found it and place his fork back (if has any).
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Dining_philosophers (whichplan) {
Form 80, 32
Line 4,449 ⟶ 4,808:
}
Dining_philosophers Random(1,2)
</syntaxhighlight>
</lang>
 
 
Line 4,484 ⟶ 4,843:
6342 - Russell eating 1- R
</pre >
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">names = <|1 -> "Aristotle", 2 -> "Kant", 3 -> "Spinoza", 4 -> "Marx", 5 -> "Russell"|>;
n = Length[names];
rp := Pause[RandomReal[4]];
PrintTemporary[Dynamic[Array[forks, n]]];
Clear[forks]; forks[_] := Null;
With[{nf = n},
ParallelDo[
With[{i1 = i, i2 = Mod[i + 1, nf, 1]},
Do[Print[names[i], " thinking"]; rp; Print[names[i], " hungry"];
CriticalSection[{forks[i1], forks[i2]},
Print[names[i], " eating"]; rp],
{2}]],
{i, nf}]];</syntaxhighlight>
{{out}}
<pre>Aristotle thinking
Kant thinking
Spinoza thinking
Marx thinking
Russell thinking
Russell hungry
Russell eating</pre>
 
=={{header|Modula-3}}==
Line 4,502 ⟶ 4,884:
 
While this implementation is not a translation of the [[#Eiffel|Eiffel]] solution, it still owes it a heads-up for the basic principle. Bertrand Meyer's ACM Webinar on [https://en.wikipedia.org/wiki/SCOOP_(software) SCOOP] directed my attention to this problem, and probably influenced the solution.
<langsyntaxhighlight lang="modula3">MODULE DiningPhilosophers EXPORTS Main;
 
IMPORT IO, Random, Thread;
Line 4,602 ⟶ 4,984:
EVAL Thread.Join(thread[i]);
END;
END DiningPhilosophers.</langsyntaxhighlight>
 
{{out}}
Line 4,622 ⟶ 5,004:
=={{header|Nim}}==
Prevents deadlocks by ordering the forks. Compile with <code>nim --threads:on c diningphilosophers.nim</code>
<langsyntaxhighlight lang="nim">import threadpool, locks, math, os, random
# to call randomize() as a seed, need to import random module
randomize()
Line 4,668 ⟶ 5,050:
createThread(threads[i], run, phils[i])
 
joinThreads(threads)</langsyntaxhighlight>
 
=={{header|OxygenBasic}}==
<langsyntaxhighlight lang="oxygenbasic">
'=========================
class RoundTableWith5Seats
Line 4,773 ⟶ 5,155:
'4 dining 8 1 1
'5 thinks 0 1 0
</syntaxhighlight>
</lang>
 
=={{header|Oz}}==
Using first-class computation spaces as transactions on dataflow variables. Computations spaces are normally used to implement constraint search engines. But here we use them to bind two variables atomically.
 
<langsyntaxhighlight lang="oz">declare
Philosophers = [aristotle kant spinoza marx russell]
Line 4,894 ⟶ 5,276:
ShowInfo = System.showInfo
in
{Start}</langsyntaxhighlight>
 
=={{header|Pascal}}==
Line 4,900 ⟶ 5,282:
 
In order to avoid deadlocks each member first takes fork with lower number.
<syntaxhighlight lang="pascal">
<lang Pascal>
program dining_philosophers;
{$mode objfpc}{$H+}
Line 5,002 ⟶ 5,384:
WaitForDinnerOver;
end.
</syntaxhighlight>
</lang>
The next variant exploits the idea of ​​a single left-handed philosopher.
<syntaxhighlight lang="pascal">
<lang Pascal>
program dining_philosophers2;
{$mode objfpc}{$H+}
Line 5,120 ⟶ 5,502:
WaitForDinnerOver;
end.
</syntaxhighlight>
</lang>
Another way to avoid deadlock: if a philosopher takes left fork but cannot take the right fork, he returns the left fork.
<syntaxhighlight lang="pascal">
<lang Pascal>
program dining_philosophers3;
{$mode objfpc}{$H+}
Line 5,224 ⟶ 5,606:
WaitForDinnerOver;
end.
</syntaxhighlight>
</lang>
And the last: deadlock can only happen if all the members are seated at the table.
 
This variant tries to avoid this situation.
<syntaxhighlight lang="pascal">
<lang Pascal>
program dining_philosophers4;
{$mode objfpc}{$H+}
Line 5,343 ⟶ 5,725:
WaitForDinnerOver;
end.
</syntaxhighlight>
</lang>
 
=={{header|Perl}}==
Line 5,351 ⟶ 5,733:
grab their forks in opposite orders.
 
<syntaxhighlight lang="perl">
<lang Perl>
use threads;
use threads::shared;
Line 5,402 ⟶ 5,784:
print "Done\n";
__END__
</syntaxhighlight>
</lang>
 
====One solution based on Coro and AnyEvent====
To prevent deadlock the philosophers must not start eating at the same time and the time between getting the first fork and getting second one must be shorter as possible.
 
<syntaxhighlight lang="perl">
<lang Perl>
#!/usr/bin/perl
use common::sense;
Line 5,419 ⟶ 5,801:
my @fork_sem;
 
$fork_sem[$_] = new Coro::Semaphore->new for (0..$#philosophers);
 
 
Line 5,448 ⟶ 5,830:
 
EV::loop;
</syntaxhighlight>
</lang>
 
=={{header|Phix}}==
Line 5,456 ⟶ 5,838:
 
If you uncomment the sleep(1)s you will probably want do the same to the terminate checks, otherwise after keying 'Q' or Escape it could take 20 seconds per diner to finish.
<!--<syntaxhighlight lang="phix">(notonline)-->
<lang Phix>integer fork1 = init_cs(),
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- threads</span>
fork2 = init_cs(),
<span style="color: #004080;">integer</span> <span style="color: #000000;">fork1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">init_cs</span><span style="color: #0000FF;">(),</span>
fork3 = init_cs(),
<span style="color: #000000;">fork2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">init_cs</span><span style="color: #0000FF;">(),</span>
fork4 = init_cs(),
<span style="color: #000000;">fork3</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">init_cs</span><span style="color: #0000FF;">(),</span>
fork5 = init_cs()
<span style="color: #000000;">fork4</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">init_cs</span><span style="color: #0000FF;">(),</span>
integer terminate = 0 -- control flag
<span style="color: #000000;">fork5</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">init_cs</span><span style="color: #0000FF;">()</span>
 
<span style="color: #004080;">integer</span> <span style="color: #000000;">terminate</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- control flag</span>
procedure person(sequence name, atom left_fork, atom right_fork)
-- (except Russell, who gets left and right the other way round)
<span style="color: #008080;">procedure</span> <span style="color: #000000;">person</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">name</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">left_fork</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">right_fork</span><span style="color: #0000FF;">)</span>
while terminate=0 do
<span style="color: #000080;font-style:italic;">-- (except Russell, who gets left and right the other way round)</span>
enter_cs(left_fork)
<span style="color: #008080;">while</span> <span style="color: #000000;">terminate</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
enter_cs(right_fork)
<span style="color: #7060A8;">enter_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">left_fork</span><span style="color: #0000FF;">)</span>
puts(1, name & " grabs forks.\n")
<span style="color: #7060A8;">enter_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">right_fork</span><span style="color: #0000FF;">)</span>
for i=1 to rand(10) do
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">name</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">" grabs forks.\n"</span><span style="color: #0000FF;">)</span>
-- if terminate then exit end if
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
puts(1, name & " is eating.\n")
<span style="color: #000080;font-style:italic;">-- if terminate then exit end if</span>
-- sleep(1)
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">name</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">" is eating.\n"</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #000080;font-style:italic;">-- sleep(1)</span>
puts(1, name & " puts forks down and leaves the dinning room.\n")
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
leave_cs(left_fork)
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">name</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">" puts forks down and leaves the dinning room.\n"</span><span style="color: #0000FF;">)</span>
leave_cs(right_fork)
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">left_fork</span><span style="color: #0000FF;">)</span>
for i=1 to rand(10) do
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">right_fork</span><span style="color: #0000FF;">)</span>
-- if terminate then exit end if
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
puts(1, name & " is thinking.\n")
<span style="color: #000080;font-style:italic;">-- if terminate then exit end if</span>
-- sleep(1)
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">name</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">" is thinking.\n"</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #000080;font-style:italic;">-- sleep(1)</span>
puts(1, name & " becomes hungry.\n")
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end while
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">name</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">" becomes hungry.\n"</span><span style="color: #0000FF;">)</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
constant r_person = routine_id("person")
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
 
<span style="color: #008080;">constant</span> <span style="color: #000000;">r_person</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"person"</span><span style="color: #0000FF;">)</span>
constant threads = {create_thread(r_person,{"Aristotle",fork1,fork2}),
create_thread(r_person,{"Kant",fork2,fork3}),
<span style="color: #008080;">constant</span> <span style="color: #000000;">threads</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r_person</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"Aristotle"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fork1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fork2</span><span style="color: #0000FF;">}),</span>
create_thread(r_person,{"Spinoza",fork3,fork4}),
<span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r_person</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"Kant"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fork2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fork3</span><span style="color: #0000FF;">}),</span>
create_thread(r_person,{"Marx",fork4,fork5}),
<span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r_person</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"Spinoza"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fork3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fork4</span><span style="color: #0000FF;">}),</span>
-- create_thread(r_person,{"Russell",fork5,fork1})} -- this will deadlock!
<span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r_person</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"Marx"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fork4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fork5</span><span style="color: #0000FF;">}),</span>
create_thread(r_person,{"Russell",fork1,fork5})}
<span style="color: #000080;font-style:italic;">-- create_thread(r_person,{"Russell",fork5,fork1})} -- this will deadlock!</span>
 
<span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r_person</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"Russell"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fork1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fork5</span><span style="color: #0000FF;">})}</span>
constant ESC = #1B
while not find(get_key(),{ESC,'q','Q'}) do
<span style="color: #008080;">constant</span> <span style="color: #000000;">ESC</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">#1B</span>
sleep(1)
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">get_key</span><span style="color: #0000FF;">(),{</span><span style="color: #000000;">ESC</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'q'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'Q'</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">do</span>
end while
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
terminate = 1
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
wait_thread(threads) -- (not strictly necessary)
<span style="color: #000000;">terminate</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
delete_cs(fork1) -- ""
<span style="color: #000000;">wait_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">threads</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (not strictly necessary)</span>
delete_cs(fork2)
<span style="color: #000000;">delete_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fork1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- ""</span>
delete_cs(fork3)
<span style="color: #000000;">delete_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fork2</span><span style="color: #0000FF;">)</span>
delete_cs(fork4)
<span style="color: #000000;">delete_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fork3</span><span style="color: #0000FF;">)</span>
delete_cs(fork5)</lang>
<span style="color: #000000;">delete_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fork4</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">delete_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fork5</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
 
=={{header|PicoLisp}}==
Line 5,514 ⟶ 5,899:
Another solution, using the Chandy/Misra method, can be found
[http://logand.com/sw/phil.l here].
<langsyntaxhighlight PicoLisplang="picolisp">(de dining (Name State)
(loop
(prinl Name ": " State)
Line 5,549 ⟶ 5,934:
'("ForkA" "ForkB" "ForkC" "ForkD" "ForkE" .) ) )
 
(push '*Bye '(mapc kill *Philosophers)) # Terminate all upon exit</langsyntaxhighlight>
Output:
<pre>Aristotle: hungry
Line 5,571 ⟶ 5,956:
using Pike Backend call_out(), this solution avoids deadlocks by adding a 20% chance that a philosopher drops the fork if he can't pick up both.
 
<langsyntaxhighlight Pikelang="pike">class Philosopher
{
string name;
Line 5,664 ⟶ 6,049:
call_out(philosophers[4]->take_forks, random(5));
return -1;
}</langsyntaxhighlight>
 
=={{header|Prolog}}==
Line 5,670 ⟶ 6,055:
Use the same solution as in Erlang (a waiter gives the forks to philosophers).<br>
Bonus : the code of an animation in XPCE is given, and statistics are displayed at the end of the process.
<langsyntaxhighlight Prologlang="prolog">dining_philosophers :-
new(D, window('Dining philosophers')),
new(S, window('Dining philosophers : statistics')),
Line 6,119 ⟶ 6,504:
 
:- pce_end_class.
</syntaxhighlight>
</lang>
[[File:Prolog-Philosophers-1.png|500px|thumb|center]]<br><br> [[File:Prolog-Philosophers-3.png|450px|thumb|center]]
 
Line 6,127 ⟶ 6,512:
put down the first and waits a few breaths, then boldly tries in the opposite order.
 
<langsyntaxhighlight PureBasiclang="purebasic">Macro Tell(Mutex, Message) ; Make a macro to easy send info back to main thread
LockMutex(Mutex)
LastElement(Queue())
Line 6,243 ⟶ 6,628:
Delay(Random(2500)+25)
ForEver
EndProcedure</langsyntaxhighlight>
 
=={{header|Python}}==
 
===With the threading library===
 
This solution avoids deadlock by never waiting for a fork while having one in hand. If
a philosopher acquires one fork but can't acquire the second, he releases the first fork
before waiting to acquire the other (which then becomes the first fork acquired).
<langsyntaxhighlight lang="python">import threading
import random
import time
Line 6,303 ⟶ 6,691:
def DiningPhilosophers():
forks = [threading.Lock() for n in range(5)]
philosopherNames = ('Aristotle','Kant','BuddhaSpinoza','Marx', 'Russel')
 
philosophers= [Philosopher(philosopherNames[i], forks[i%5], forks[(i+1)%5]) \
Line 6,315 ⟶ 6,703:
print ("Now we're finishing.")
 
DiningPhilosophers()</langsyntaxhighlight>
 
===With the multiprocessing library===
 
This version uses the multiprocessing library to achieve concurrency on multiple CPUs. (Threads run on a single CPU and are run in "turns". The Python threading library simulate concurrency.)
 
Some other improvements and modifications: configurable number of philosophers, "more deterministic" randomization by pre-allocating the thinking and dining schedules, time scaling to allow faster runs producing results that are essentially the same, collect statistics on wait times, attempt to check for deadlock, adds more algorithms, including a naive to demonstrate deadlock and two symmetry breaking one versions.
 
Changed forks to chopsticks. Sorry Edsger, nobody (not even philosophers) need two forks to eat with. Furthermore, using 'fork' may cause confusion, since fork has a meaning in the context of concurrent programming.
 
<syntaxhighlight lang="python">
 
"""Dining philosophers with multiprocessing module."""
import multiprocessing as mp
import random
import time
 
# Dining philosophers. See also comments at the threading
# version. Improvements, modifications:
# Support variable number of philosophers.
# "More deterministic" randomization by prealocating the schedules.
# Use scaling to allow faster runs producing results that are
# essentially the same.
# Collect statistics on wait times.
 
SCALE = 0.2
THINK = (3, 13)
DINE = (1, 10)
 
class Philosopher(mp.Process):
"""Independently running philosopher processes."""
def __init__(self, idx, name, run_flag, chopstick_left, chopstick_right,
stats, schedule_think, schedule_dine):
mp.Process.__init__(self)
self.idx = idx
self.name = name
self.run_flag = run_flag
self.chopstick_left = chopstick_left
self.chopstick_right = chopstick_right
self.stats = stats
self.schedule_think = schedule_think
self.schedule_dine = schedule_dine
self.counter = 0
self.num_dined = 0
self.hungry_time_total = 0.0
self.hungry_time_max = 0.0
 
def run(self):
while self.run_flag.value and self.counter < len(self.schedule_think):
# Philosopher is thinking (but really is sleeping).
time.sleep(self.schedule_think[self.counter]*SCALE)
duration = -time.perf_counter()
print(f'{self.name} is hungry', flush=True)
self.get_chopsticks2()
duration += time.perf_counter()
self.hungry_time_total += duration
self.hungry_time_max = max(self.hungry_time_max, duration)
self.dining()
# Populate self.stats:
self.stats.put({'name': self.name,
'num_dined': self.num_dined,
'hungry_time_total': self.hungry_time_total,
'hungry_time_max': self.hungry_time_max})
 
def get_chopsticks(self):
"""Use swaps and do not hold on to chopsticks."""
chopstick1, chopstick2 = self.chopstick_left, self.chopstick_right
 
while True:
chopstick1.acquire(True)
locked = chopstick2.acquire(False)
if locked:
return
chopstick1.release()
print(f'{self.name} swaps chopsticks', flush=True)
chopstick1, chopstick2 = chopstick2, chopstick1
 
def get_chopsticks0(self):
"""Naive greedy implementation to trigger deadlock."""
self.chopstick_left.acquire(True)
time.sleep(0.1)
self.chopstick_right.acquire(True)
 
def get_chopsticks1(self):
"""Break the symmetry by having one philosopher to be left handed."""
if self.idx == 0:
chopstick1, chopstick2 = self.chopstick_left, self.chopstick_right
else:
chopstick1, chopstick2 = self.chopstick_right, self.chopstick_left
chopstick1.acquire(True)
locked = chopstick2.acquire(False)
if not locked:
chopstick1.release()
chopstick2.acquire(True)
chopstick1.acquire(True)
 
def get_chopsticks2(self):
"""Break the symmetry by having the even numbered philosophers to be
left handed."""
if self.idx == 0:
chopstick1, chopstick2 = self.chopstick_left, self.chopstick_right
else:
chopstick1, chopstick2 = self.chopstick_right, self.chopstick_left
chopstick1.acquire(True)
locked = chopstick2.acquire(False)
if not locked:
chopstick1.release()
chopstick2.acquire(True)
chopstick1.acquire(True)
 
def dining(self):
"""Dining with two chopsticks."""
print(f'{self.name} starts eating', flush=True)
self.num_dined += 1
time.sleep(self.schedule_dine[self.counter]*SCALE)
self.counter += 1
print(f'{self.name} finishes eating and leaves to think.', flush=True)
self.chopstick_left.release()
self.chopstick_right.release()
 
def performance_report(stats):
"""Print some stats about the wait times."""
print("Performance report:")
for queue in stats:
data = queue.get()
print(f"Philosopher {data['name']} dined {data['num_dined']} times. ")
print(f" Total wait : {data['hungry_time_total'] / SCALE}")
print(f" Max wait : {data['hungry_time_max'] / SCALE}")
if data['num_dined'] > 0:
print(f" Average wait: "
f"{data['hungry_time_total'] / data['num_dined']/SCALE}")
 
def generate_philosophers(names, run_flag, chopsticks, stats, max_dine):
"""Gebnerate a list of philosophers with random schedules."""
num = len(names)
philosophers = [Philosopher(i, names[i], run_flag,
chopsticks[i % num],
chopsticks[(i+1) % num],
stats[i],
[random.uniform(THINK[0], THINK[1])
for j in range(max_dine)],
[random.uniform(DINE[0], DINE[1])
for j in range(max_dine)])
for i in range(num)]
return philosophers
 
def generate_philosophers0(names, run_flag, chopsticks, stats,
schedule_think, schedule_dine):
"""Allows the use of a predetermined thinking and dining schedule.
This may aid in triggering a deadlock."""
num = len(names)
philosophers = [Philosopher(i, names[i], run_flag,
chopsticks[i % num],
chopsticks[(i+1) % num],
stats[i],
schedule_think[i],
schedule_dine[i])
for i in range(num)]
return philosophers
 
def dining_philosophers(philosopher_names=(('Aristotle', 'Kant',
'Buddha', 'Marx', 'Russel')),
num_sec=100, max_dine=100):
"""Main routine."""
num = len(philosopher_names)
chopsticks = [mp.Lock() for n in range(num)]
random.seed(507129)
run_flag = mp.Value('b', True)
stats = [mp.Queue() for n in range(num)]
 
philosophers = generate_philosophers(philosopher_names, run_flag,
chopsticks, stats, max_dine)
 
# Use the following when trying to trigger a deadlock in conjunction with
# get_chopsticks0():
#philosophers = generate_philosophers0(philosopher_names, run_flag,
# chopsticks, stats, [3]*max_dine,
# [5]*max_dine)
 
for phi in philosophers:
phi.start()
time.sleep(num_sec*SCALE)
run_flag.value = False
print("Now we're finishing.", flush=True)
# We want to allow the philosophers to finish their meal. In fact,
# we even allow them to still start eating if they are presently
# hungry. This means we may need to wait at most num*DINE[1].
wait_time = num*DINE[1]
while wait_time >= 0 and sum(p.is_alive() for p in philosophers) > 0:
time.sleep(1)
wait_time -= 1.0
if wait_time < 0:
for phi in philosophers:
if phi.is_alive():
print(f"Ooops, {phi.name} has not finished!!")
phi.terminate()
return 1
performance_report(stats)
 
if __name__ == '__main__':
dining_philosophers()
 
</syntaxhighlight>
 
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 6,407 ⟶ 6,997:
 
(run)
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 6,413 ⟶ 7,003:
{{works with|rakudo|2015-09-09}}
We use locking mutexes for the forks, and a lollipop to keep the last person who finished eating from getting hungry until the next person finishes eating, which prevents a cycle of dependency from forming. The algorithm should scale to many philosophers, and no philosopher need be singled out to be left-handed, so it's fair in that sense.
<syntaxhighlight lang="raku" perl6line>class Fork {
has $!lock = Lock.new;
method grab($who, $which) {
Line 6,463 ⟶ 7,053:
}
sink await @philosophers;
}</langsyntaxhighlight>
{{out}}
<pre>Aristotle grabbing left fork
Line 6,529 ⟶ 7,119:
 
Deadlocks are eliminated by the method of acquiring the resources (forks): &nbsp; both forks are (attempted to be) grabbed at the same time (by both hands). &nbsp;
<langsyntaxhighlight lang="rexx">/*REXX program demonstrates a solution in solving the dining philosophers problem. */
signal on halt /*branches to HALT: (on Ctrl─break).*/
parse arg seed diners /*obtain optional arguments from the CL*/
Line 6,576 ⟶ 7,166:
else if @.p.state=='thinking' then @.p.state=0
end /*p*/ /*[↑] P (person)≡ dining philosophers.*/
return /*now, have some human beans grab forks*/</langsyntaxhighlight>
{{out|output|text=&nbsp; &nbsp; (some middle and end portions have been elided):
<pre>
Line 6,606 ⟶ 7,196:
 
{{works with|Ruby|1.8.7}}
<langsyntaxhighlight lang="ruby">require 'mutex_m'
 
class Philosopher
Line 6,675 ⟶ 7,265:
end
philosophers.each {|thread| thread.join}</langsyntaxhighlight>
 
=={{header|Rust}}==
A Rust implementation of a solution for the Dining Philosophers Problem. We prevent a deadlock by using Dijkstra's solution of making a single diner "left-handed." That is, all diners except one pick up the chopstick "to their left" and then the chopstick "to their right." The remaining diner performs this in reverse.
 
<langsyntaxhighlight lang="rust">use std::thread;
use std::sync::{Mutex, Arc};
 
Line 6,742 ⟶ 7,332:
h.join().unwrap();
}
}</langsyntaxhighlight>
 
=={{header|Simula}}==
<langsyntaxhighlight lang="simula">COMMENT
! DEADLOCK IS PREVENTED BY REVERSING THE ORDER OF TAKING THE CHOPSTICKS FOR THE LAST PHILOSOPHER.
! THAT MEANS ALL PHILOSOPHERS FIRST TAKE THE LEFT CHOPSTICK, THEN THE RIGHT CHOPSTICK.
Line 6,906 ⟶ 7,496:
 
END;
END.</langsyntaxhighlight>
{{in}}
<pre>
Line 7,008 ⟶ 7,598:
This solution is similar to the Python solution, except this uses Semaphore instances for forks and an OrderedCollection to hold sequence of forks and philosophers around the table. The method #pickUpForks releases and retries after a small delay till it has both. <b>Special note:</b> Smalltalk concurrent processes are created by sending the message #fork to a block. Do not confuse this method name with the forks of the problem domain.
 
<langsyntaxhighlight Smalltalklang="smalltalk">'From Squeak3.7 of ''4 September 2004'' [latest update: #5989] on 13 October 2011 at 2:44:42 pm'!
Object subclass: #Philosopher
instanceVariableNames: 'table random name seat forks running'
Line 7,105 ⟶ 7,695:
#('Aristotle' 'Kant' 'Buddha' 'Marx' 'Russel' )
do: [:aName | Philosopher new beginDining: aName at: diningTable]! !
</syntaxhighlight>
</lang>
 
=={{header|Tcl}}==
{{works with|Tcl|8.6}}
<langsyntaxhighlight lang="tcl">package require Thread
 
foreach name {Aristotle Kant Spinoza Marx Russel} {
Line 7,176 ⟶ 7,766:
foreach t $tasks {
thread::send -async $t thread::exit
}</langsyntaxhighlight>
 
=={{header|VBA}}==
Line 7,182 ⟶ 7,772:
philosopher separately, as if in separate threads. Program terminates after max count is reached. Statistics show how many
program ticks are spent at each step at the dining table.
<langsyntaxhighlight lang="vb">'The combination of holding to the second fork
'(HOLDON=True) and all philosophers start
'with same hand (DIJKSTRASOLUTION=False) leads
Line 7,277 ⟶ 7,867:
dine
show
End Sub</langsyntaxhighlight>{{out}}
<pre>Stats Gets Gets Eats Puts Puts Thinks
First Second Spag- First Second About
Line 7,296 ⟶ 7,886:
* In the third mode, each fork is numbered. The philosopher will always pick up a lower number fork before a higher number fork, thus preventing a dead-lock while guaranteeing forward progress.
 
<langsyntaxhighlight lang="vbnet">Imports System.Threading
Module Module1
Public rnd As New Random
Line 7,345 ⟶ 7,935:
End Sub
 
End Module</langsyntaxhighlight>
 
<langsyntaxhighlight lang="vbnet">Class Fork
Private ReadOnly m_Number As Integer
Public Sub New(ByVal number As Integer)
Line 7,357 ⟶ 7,947:
End Get
End Property
End Class</langsyntaxhighlight>
 
<langsyntaxhighlight lang="vbnet">MustInherit Class PhilosopherBase
Implements IDisposable
 
Line 7,389 ⟶ 7,979:
 
Public MustOverride Sub MainLoop()
End Class</langsyntaxhighlight>
 
=== Deadlock ===
 
<langsyntaxhighlight lang="vbnet">Class SelfishPhilosopher
Inherits PhilosopherBase
Public Sub New(ByVal name As String, ByVal right As Fork, ByVal left As Fork)
Line 7,423 ⟶ 8,013:
End Sub
 
End Class</langsyntaxhighlight>
 
=== Live Lock ===
<langsyntaxhighlight lang="vbnet">Class SelflessPhilosopher
Inherits PhilosopherBase
 
Line 7,466 ⟶ 8,056:
End Sub
 
End Class</langsyntaxhighlight>
 
=== Working ===
<langsyntaxhighlight lang="vbnet">Class WisePhilosopher
Inherits PhilosopherBase
Public Sub New(ByVal name As String, ByVal right As Fork, ByVal left As Fork)
Line 7,509 ⟶ 8,099:
End Sub
 
End Class</langsyntaxhighlight>
 
=={{header|Wren}}==
This is loosely based on the Kotlin entry.
 
However, Wren uses co-operatively scheduled fibers rather than threads for concurrency and, as long as a philosoper waits until he can pick up both forks to eat, deadlock is impossible because only one fiber can run at a time.
<syntaxhighlight lang="wren">import "random" for Random
import "scheduler" for Scheduler
import "timer" for Timer
 
var Rand = Random.new()
 
var ForkInUse = List.filled(5, false)
 
class Fork {
construct new(name, index) {
_name = name
_index = index
}
 
index { _index }
 
pickUp(philosopher) {
System.print(" %(philosopher) picked up %(_name)")
ForkInUse[index] = true
}
 
putDown(philosopher) {
System.print(" %(philosopher) put down %(_name)")
ForkInUse[index] = false
}
}
 
class Philosopher {
construct new(pname, f1, f2) {
_pname = pname
_f1 = f1
_f2 = f2
}
 
delay() { Timer.sleep(Rand.int(300) + 100) }
 
eat() {
(1..5).each { |bite| // limit to 5 bites say
while (true) {
System.print("%(_pname) is hungry")
if (!ForkInUse[_f1.index] && !ForkInUse[_f2.index]) {
_f1.pickUp(_pname)
_f2.pickUp(_pname)
break
}
System.print("%(_pname) is unable to pick up both forks")
// try again later
delay()
}
System.print("%(_pname) is eating bite %(bite)")
// allow time to eat
delay()
_f2.putDown(_pname)
_f1.putDown(_pname)
// allow other philospohers time to pick up forks
delay()
}
}
}
 
var diningPhilosophers = Fn.new { |names|
var size = names.count
var forks = List.filled(size, null)
for (i in 0...size) forks[i] = Fork.new("Fork %(i + 1)", i)
var philosophers = []
var i = 0
for (n in names) {
var i1 = i
var i2 = (i + 1) % size
if (i2 < i1) {
i1 = i2
i2 = i
}
var p = Philosopher.new(n, forks[i1], forks[i2])
philosophers.add(p)
i = i + 1
}
// choose a philosopher at random to start eating
var r = Rand.int(size)
// schedule the others to eat later
for (i in 0...size) if (i != r) Scheduler.add { philosophers[i].eat() }
philosophers[r].eat()
}
 
var names = ["Aristotle", "Kant", "Spinoza", "Marx", "Russell"]
diningPhilosophers.call(names)</syntaxhighlight>
 
=={{header|zkl}}==
The model used here is five seats, each with two forks. Sn:(Fn,Fn+1). Seat(n+1) shares a fork with seat n and so on. Fork are represented by an atomic bool, a bool that changes state atomically. Each philosopher is a thread. Each philosopher is ambidextrous, leading with a random hand. If the trailing hand can not get a fork, the already in hand fork is put down.
<langsyntaxhighlight lang="zkl">var [const] forks=(5).pump(List,Atomic.Bool.fp(False)), // True==fork in use
seats=(5).pump(List,'wrap(n){ List(forks[n],forks[(n+1)%5]) });
fcn sitAndEat(name,n){ // assigned seating
Line 7,538 ⟶ 8,219:
sitAndEat(name,seat);
}
}</langsyntaxhighlight>
The setIf method atomically sets the bool to the first value if it is currently the second value.
<langsyntaxhighlight lang="zkl">T("Aristotle", "Kant", "Spinoza", "Marx", "Russell").enumerate()
.apply(philo.launch);
 
Atomic.sleep(100000); // hang out in the REPL, aka thread keep alive</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits