如果代码难以理解,我道歉。 这是经典的餐饮哲学家问题,有5位哲学家正在吃饭,但只有5支 - 你需要两只才能吃。
如果有人有兴趣,这些是说明: http://www.kth.se/polopoly_fs/1.260940!/Menu/general/column-content/attachment/philosophers.pdf
无论如何,这里是代码,筷子过程代码:
-module(chopstick).
-export([start/0]).
start() ->
spawn_link(fun() -> init() end).
init() ->
available().
available() ->
receive
{request, From} ->
From ! granted,
gone();
quit ->
ok
end.
gone() ->
receive
returned ->
available();
quit ->
ok
end.
哲学家流程代码:
-module(eater).
-import(timer, [sleep/1]).
-import(random, [uniform/1]).
-export([start/5, dream/5, eat/5, wait/5]).
start(Hungry, Right, Left, Name, Ctrl) ->
dream(Hungry, Right, Left, Name, Ctrl).
**%This was wrong, it should say start(Hungry, Right, Left, Name, Ctrl) ->
spawn_link(fun() -> dream(Hungry, Right, Left, Name, Ctrl) end).**
dream(Hungry, Right, Left, Name, Ctrl) ->
Time = 500+uniform:random(500), **%This was wrong, it should say random:uniform**
timer:sleep(Time),
Right! {request, self()},
Left! {request, self()},
%skicka {request, self()} till två pinnar
wait(Hungry, Right, Left, Name, Ctrl).
wait(Hungry, Right, Left, Name, Ctrl) ->
receive
granted ->
io:format("~s received a chopstick~n", [Name]),
receive
granted ->
io:format("~s received a chopstick~n", [Name]),
io:format("~s started eating~n", [Name]),
eat(Hungry, Right, Left, Name, Ctrl)
end;
_ -> wait(Hungry, Right, Left, Name, Ctrl)
end.
eat(Hungry, Right, Left, Name, Ctrl) ->
Time = 500+uniform:random(500), **%This was wrong, it should say random:uniform**
timer:sleep(Time),
Right! returned,
Left! returned,
io:format("~s put back two chopsticks~n", [Name]),
if
Hungry =< 1 ->
Ctrl ! done;
true ->
dream(Hungry-1, Right, Left, Name, Ctrl)
end.
最后主持人进程:
-module(dinner).
-export([start/0]).
start() ->
spawn(fun() -> init() end).
init() ->
C1 = chopstick:start(),
C2 = chopstick:start(),
C3 = chopstick:start(),
C4 = chopstick:start(),
C5 = chopstick:start(),
Ctrl = self(),
eater:start(5, C1, C2, "Confucios", Ctrl), **% This is where it crashes**
eater:start(5, C2, C3, "Avicenna", Ctrl),
eater:start(5, C3, C4, "Plato", Ctrl),
eater:start(5, C4, C5, "Kant", Ctrl),
eater:start(5, C5, C1, "Descartes", Ctrl),
wait(5, [C1, C2, C3, C4, C5]).
wait(0, Chopsticks) ->
lists:foreach(fun(C) -> C ! quit end, Chopsticks);
wait(N, Chopsticks) ->
receive
done ->
wait(N-1, Chopsticks);
abort ->
erlang:exit(abort)
end.
输出:
11> dinner:start().
<0.85.0>
12>
=ERROR REPORT==== 10-Nov-2011::02:19:10 ===
Error in process <0.85.0> with exit value: {undef,[{uniform,random,[500]}, {eater,dream,5},{dinner,init,0}]}
非常感谢,如果你读完所有这些,我还没有学会如何阅读erlang的错误报告。如果可以,并想告诉我这意味着什么,请做。
答案 0 :(得分:8)
我认为问题在于您有三个模块:dinner
,eater
和chopstick
,但尝试在philospher:start
中调用dinner:init/0
功能。请改为eater:start
。
第二个问题是生成随机数时模块和函数名的顺序;将uniform:random
替换为random:uniform
中的eater.erl
:
1> dinner:start().
<0.35.0>
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Avicenna received a chopstick
Avicenna received a chopstick
Avicenna started eating
...
这很快就显示了第三个问题 - 我们应该从第一个错误报告中发现 - 食者实际上并不在他们自己的过程中。因此,请修改eater.erl
,以便start()
函数显示:
start(Hungry, Right, Left, Name, Ctrl) ->
spawn_link(fun() -> dream(Hungry, Right, Left, Name, Ctrl) end).
现在它按预期工作:
1> dinner:start().
<0.35.0>
Confucios received a chopstick
Plato received a chopstick
Confucios received a chopstick
Confucios started eating
Descartes received a chopstick
Kant received a chopstick
Confucios put back two chopsticks
Avicenna received a chopstick
...
感谢。这很有趣。
答案 1 :(得分:2)
在您呼叫的任何地方进行更改: 至 uniform:random/1
random:uniform/1
,异常将消失